Repository: fschutt/printpdf (language: rust)

Issue:
Build error with target=wasm32-unknown-unknown
It seems this crate is intended to work with wasm32, however, there is a build error when compiling with target `wasm32`:

`cargo build --example image --release --features embedded_images --target=wasm32-unknown-unknown`

```
error[E0599]: no method named `offset` found for reference `&js_sys_date::OffsetDateTime` in the current scope
   --> src/document_info.rs:104:23
    |
104 |     let offset = date.offset();
    |                       ^^^^^^ method not found in `&OffsetDateTime`

error[E0277]: the trait bound `u8: From<u32>` is not satisfied
   --> src/document_info.rs:109:9
    |
109 |         u8::from(date.month()),
    |         ^^ the trait `From<u32>` is not implemented for `u8`
    |
    = help: the following other types implement trait `From<T>`:
              <u8 as From<bool>>
              <u8 as From<deranged::ranged_u8::RangedU8<MIN, MAX>>>
              <u8 as From<time::month::Month>>
              <u8 as From<NonZeroU8>>
```


Discussion / hints:
i also tried without js-sys as i saw it is optional, but i got this new build error:

`cargo run --example image --release --features embedded_images --target=wasm32-unknown-unknown --no-default-features`
```
   Compiling printpdf v0.7.0 (/home/hubert/Documents/corners_ws/printpdf)
error[E0599]: no method named `offset` found for reference `&unix_epoch_stub_date::OffsetDateTime` in the current scope
   --> src/document_info.rs:104:23
    |
104 |     let offset = date.offset();
    |                       ^^^^^^ method not found in `&OffsetDateTime`

error[E0277]: the trait bound `u8: From<u32>` is not satisfied
   --> src/document_info.rs:109:9
    |
109 |         u8::from(date.month()),
    |         ^^ the trait `From<u32>` is not implemented for `u8`
    |
    = help: the following other types implement trait `From<T>`:
              <u8 as From<bool>>
              <u8 as From<deranged::ranged_u8::RangedU8<MIN, MAX>>>
              <u8 as From<time::month::Month>>
              <u8 as From<NonZeroU8>>
```
So the question is: how to correctly compile for **wasm32** target?
breaking change from [bb2645e](https://github.com/fschutt/printpdf/commit/bb2645e5845789009e6f9abc11489908bdf9314c)
as a side note, i guess this regression could be caught with a CI pipeline that also check for wasm32 target compilation
i got the same error ...i just add the follow dependencies  and it work ...dont ask me how... it just did

[dependencies]
chrono = "0.4"
wasm-bindgen = "0.2.91"
serde-wasm-bindgen = "0.6.3"
serde_bytes = "0.11.9"

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index d85dcaa..1a322ea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,11 +14,17 @@ cache: cargo
 matrix:
   fast_finish: true
 
+install:
+  - rustup target wasm32-unknown-unknown
+
 script:
   - cargo check --verbose --examples
   - cargo check --verbose --no-default-features
   - cargo check --verbose --features="embedded_images"
   - cargo test --verbose
+  - cargo check --verbose --examples --target wasm32-unknown-unknown
+  - cargo check --verbose --no-default-features --target wasm32-unknown-unknown
+  - cargo check --verbose --features="embedded_images" --target wasm32-unknown-unknown
 
 notifications:
   email: false
diff --git a/src/date.rs b/src/date.rs
index cfd0caf..354def5 100644
--- a/src/date.rs
+++ b/src/date.rs
@@ -8,11 +8,13 @@ pub use self::js_sys_date::OffsetDateTime;
 pub use self::unix_epoch_stub_date::OffsetDateTime;
 
 #[cfg(not(any(target_arch = "wasm32", target_os = "unknown")))]
-pub use time::OffsetDateTime;
+pub use time::{OffsetDateTime, UtcOffset};
 
 #[cfg(all(feature = "js-sys", target_arch = "wasm32", target_os = "unknown"))]
 mod js_sys_date {
     use js_sys::Date;
+    use time::Month;
+
     #[derive(Debug, Clone)]
     pub struct OffsetDateTime(Date);
     impl OffsetDateTime {
@@ -35,33 +37,61 @@ mod js_sys_date {
         }
 
         #[inline(always)]
-        pub fn year(&self) -> u32 {
-            self.0.get_full_year()
+        pub fn year(&self) -> i32 {
+            self.0.get_full_year() as i32
         }
 
         #[inline(always)]
-        pub fn month(&self) -> u32 {
-            self.0.get_month() + 1u32
+        pub fn month(&self) -> Month {
+            match self.0.get_month() {
+                0 => Month::January,
+                1 => Month::February,
+                2 => Month::March,
+                3 => Month::April,
+                4 => Month::May,
+                5 => Month::June,
+                6 => Month::July,
+                7 => Month::August,
+                8 => Month::September,
+                9 => Month::October,
+                10 => Month::November,
+                11 => Month::December,
+                _ => unreachable!(),
+            }
         }
 
         #[inline(always)]
-        pub fn day(&self) -> u32 {
-            self.0.get_date()
+        pub fn day(&self) -> u8 {
+            self.0.get_date() as u8
         }
 
         #[inline(always)]
-        pub fn hour(&self) -> u32 {
-            self.0.get_hours()
+        pub fn hour(&self) -> u8 {
+            self.0.get_hours() as u8
         }
 
         #[inline(always)]
-        pub fn minute(&self) -> u32 {
-            self.0.get_minutes()
+        pub fn minute(&self) -> u8 {
+            self.0.get_minutes() as u8
         }
 
         #[inline(always)]
-        pub fn second(&self) -> u32 {
-            self.0.get_seconds()
+        pub fn second(&self) -> u8 {
+            self.0.get_seconds() as u8
+        }
+
+        #[inline]
+        pub fn offset(&self) -> super::UtcOffset {
+            let offset = self.0.get_timezone_offset();
+            let truncated_offset = offset as i32;
+            let hours = (truncated_offset % 60).try_into().unwrap();
+            let minutes = (truncated_offset / 60).try_into().unwrap();
+            let seconds = ((offset * 60.) % 60.) as i8;
+            super::UtcOffset {
+                hours,
+                minutes,
+                seconds,
+            }
         }
     }
 }
@@ -69,6 +99,8 @@ mod js_sys_date {
 #[cfg(not(feature = "js-sys"))]
 #[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
 mod unix_epoch_stub_date {
+    use time::Month;
+
     #[derive(Debug, Clone)]
     pub struct OffsetDateTime;
     impl OffsetDateTime {
@@ -89,33 +121,65 @@ mod unix_epoch_stub_date {
         }
 
         #[inline(always)]
-        pub fn year(&self) -> u32 {
+        pub fn year(&self) -> i32 {
             1970
         }
 
         #[inline(always)]
-        pub fn month(&self) -> u32 {
-            1
+        pub fn month(&self) -> Month {
+            Month::January
         }
 
         #[inline(always)]
-        pub fn day(&self) -> u32 {
+        pub fn day(&self) -> u8 {
             1
         }
 
         #[inline(always)]
-        pub fn hour(&self) -> u32 {
+        pub fn hour(&self) -> u8 {
             0
         }
 
         #[inline(always)]
-        pub fn minute(&self) -> u32 {
+        pub fn minute(&self) -> u8 {
             0
         }
 
         #[inline(always)]
-        pub fn second(&self) -> u32 {
+        pub fn second(&self) -> u8 {
             0
         }
+
+        #[inline]
+        pub fn offset(&self) -> super::UtcOffset {
+            super::UtcOffset {
+                hours: 0,
+                minutes: 0,
+                seconds: 0,
+            }
+        }
+    }
+}
+
+#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct UtcOffset {
+    hours: i8,
+    minutes: i8,
+    seconds: i8,
+}
+
+#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
+impl UtcOffset {
+    pub const fn whole_hours(self) -> i8 {
+        self.hours
+    }
+
+    pub const fn is_negative(self) -> bool {
+        self.hours < 0 || self.minutes < 0 || self.seconds < 0
+    }
+
+    pub const fn minutes_past_hour(self) -> i8 {
+        self.minutes
     }
 }
diff --git a/src/document_info.rs b/src/document_info.rs
index ae2a2c9..1d15010 100644
--- a/src/document_info.rs
+++ b/src/document_info.rs
@@ -117,6 +117,7 @@ fn to_pdf_time_stamp_metadata(date: &OffsetDateTime) -> String {
 }
 
 #[cfg(test)]
+#[cfg(not(any(target_arch = "wasm32", target_os = "unknown")))]
 mod tests {
     use time::{Date, Month, UtcOffset};
 


Test patch: