Add waker and conversion to raw pointer (#16)

diff --git a/src/task.rs b/src/task.rs
index 80953f4..b26c082 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -4,7 +4,7 @@
 use core::mem::{self, ManuallyDrop};
 use core::pin::Pin;
 use core::ptr::NonNull;
-use core::task::{Context, Poll};
+use core::task::{Context, Poll, Waker};
 
 use crate::header::Header;
 use crate::raw::RawTask;
@@ -264,6 +264,41 @@
             &*raw
         }
     }
+
+    /// Converts this task into a raw pointer to the tag.
+    pub fn into_raw(self) -> *const T {
+        let offset = Header::offset_tag::<T>();
+        let ptr = self.raw_task.as_ptr();
+        mem::forget(self);
+
+        unsafe { (ptr as *mut u8).add(offset) as *const T }
+    }
+
+    /// Converts a raw pointer to the tag into a task.
+    ///
+    /// This method should only be used with raw pointers returned from [`into_raw`].
+    ///
+    /// [`into_raw`]: #method.into_raw
+    pub unsafe fn from_raw(raw: *const T) -> Task<T> {
+        let offset = Header::offset_tag::<T>();
+        let ptr = (raw as *mut u8).sub(offset) as *mut ();
+
+        Task {
+            raw_task: NonNull::new_unchecked(ptr),
+            _marker: PhantomData,
+        }
+    }
+
+    /// Returns a waker associated with this task.
+    pub fn waker(&self) -> Waker {
+        let ptr = self.raw_task.as_ptr();
+        let header = ptr as *const Header;
+
+        unsafe {
+            let raw_waker = ((*header).vtable.clone_waker)(ptr);
+            Waker::from_raw(raw_waker)
+        }
+    }
 }
 
 impl<T> Drop for Task<T> {