`ic-test-state-machine` failed to decode response as candid type

I have a test function using ic-test-state-machine:

pub fn suggections(
    env: &StateMachine,
    canister_id: Principal,
    offset: Option<i32>,
    limit: Option<i64>,
) -> Result<Vec<Suggection>, ic_test_state_machine_client::CallError> {
    let res: Result<(Vec<Suggection>,), CallError> =
        query_candid(env, canister_id, "suggections", (offset, limit));

    assert!(res.is_ok(), "should okkkkkkkkkkkkkkk pls");
    res.map(|r| r.0)
}

Here is my Suggection’s definition, it had implment CandidType:

#[derive(
    Queryable,
    Debug,
    CandidType,
    Serialize,
    Deserialize,
    Selectable,
    Insertable,
    Default,
    Clone,
    Identifiable,
    PartialEq,
)]
#[diesel(primary_key(id))]
#[diesel(table_name = crate::schema::suggections)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Suggection {
    pub id: i32,
    pub title: String,
    pub content: Option<String>,
    pub principal: String,
    pub created_at: time::OffsetDateTime,
}

The time::OffsetDateTime also implmented CandidType:

#[cfg(feature = "icp")]
impl CandidType for OffsetDateTime {
    fn _ty() -> Type {
        Type::Nat
    }

    fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
    where
        S: Serializer,
    {
        let res = self.unix_timestamp_nanos();
        let res: u128 = res.abs().try_into().unwrap();
        let nat = candid::Nat::from(res);
        let res = serializer.serialize_nat(&nat);
        res
    }
}

But when i run

cargo test --package suggection_box --target x86_64-unknown-linux-musl -- --nocapture

I got:

thread 'get_suggections_should_work' panicked at 'Failed to decode response as candid type (alloc::vec::Vec<suggection_box::models::Suggection>,):
error: Fail to decode argument 0 from table0 to vec record {
  id : int32;
  title : text;
  "principal" : text;
  content : opt text;
  created_at : nat;
}
bytes: [68, 73, 68, 76, 3, 109, 1, 108, 5, 219, 183, 1, 117, 152, 171, 236, 129, 1, 113, 174, 157, 177, 144, 1, 113, 185, 154, 222, 203, 1, 2, 170, 172, 217, 208, 6, 125, 110, 113, 1, 0, 1, 1, 0, 0, 0, 7, 116, 105, 116, 108, 101, 95, 49, 63, 115, 54, 109, 53, 119, 45, 117, 51, 55, 99, 107, 45, 119, 102, 121, 52, 102, 45, 120, 103, 108, 108, 116, 45, 106, 101, 114, 104, 117, 45, 97, 120, 51, 51, 109, 45, 102, 114, 110, 53, 115, 45, 115, 97, 114, 105, 53, 45, 115, 106, 99, 53, 100, 45, 55, 108, 55, 97, 110, 45, 120, 97, 101, 1, 9, 99, 111, 110, 116, 101, 110, 116, 95, 50, 128, 160, 240, 150, 224, 181, 240, 2]
utf8: DIDLml۷u���q����q��������}nqtitl

Compiled successful. And deploy canister to local, dfx call canister works:

root@DESKTOP-D2P8H7D:# dfx canister call suggection_box suggections
(
  vec {
    record {
      id = 1 : int32;
      title = "title";
      "principal" = "****************************************";
      content = null;
      created_at = 1_687_677_000_000_000 : nat;
    };
  },
)

I am new to rust. I seem that the candid’s decode_args in with_candid function

/// A helper function that we use to implement both [`call_candid`] and
/// [`query_candid`].
pub fn with_candid<Input, Output>(
    input: Input,
    f: impl FnOnce(Vec<u8>) -> Result<WasmResult, UserError>,
) -> Result<Output, CallError>
where
    Input: ArgumentEncoder,
    Output: for<'a> ArgumentDecoder<'a>,
{
    let in_bytes = encode_args(input).expect("failed to encode args");
    match f(in_bytes) {
        Ok(WasmResult::Reply(out_bytes)) => Ok(decode_args(&out_bytes).unwrap_or_else(|e| {
            panic!(
                "Failed to decode response as candid type {}:\nerror: {}\nbytes: {:?}\nutf8: {}",
                std::any::type_name::<Output>(),
                e,
                out_bytes,
                String::from_utf8_lossy(&out_bytes),
            )
        })),
        Ok(WasmResult::Reject(message)) => Err(CallError::Reject(message)),
        Err(user_error) => Err(CallError::UserError(user_error)),
    }
}

can not find the CandidType implmentation in time crate for time::OffsetDateTime struct.

Similar test:

#[test]
fn test_candid_decode() {
    let vecc: Vec<u8> = vec![
        68, 73, 68, 76, 3, 109, 1, 108, 5, 219, 183, 1, 117, 152, 171, 236, 129, 1, 113, 174, 157,
        177, 144, 1, 113, 185, 154, 222, 203, 1, 2, 170, 172, 217, 208, 6, 125, 110, 113, 1, 0, 1,
        1, 0, 0, 0, 7, 116, 105, 116, 108, 101, 95, 49, 63, 115, 54, 109, 53, 119, 45, 117, 51, 55,
        99, 107, 45, 119, 102, 121, 52, 102, 45, 120, 103, 108, 108, 116, 45, 106, 101, 114, 104,
        117, 45, 97, 120, 51, 51, 109, 45, 102, 114, 110, 53, 115, 45, 115, 97, 114, 105, 53, 45,
        115, 106, 99, 53, 100, 45, 55, 108, 55, 97, 110, 45, 120, 97, 101, 1, 9, 99, 111, 110, 116,
        101, 110, 116, 95, 50, 128, 160, 240, 150, 224, 181, 240, 2,
    ];
    let res: Result<(Vec<Suggection>,), candid::Error> = candid::decode_args(&vecc);
    println!("test_candid_decode: {:?}", res);

    assert!(res.is_ok());
}

run cargo test --package suggection_box --target x86_64-unknown-linux-musl -- --nocapture and got:

running 4 tests
test_candid_decode: Err(Custom(Fail to decode argument 0 from table0 to vec record {
  id : int32;
  title : text;
  "principal" : text;
  content : opt text;
  created_at : nat;
}

Caused by:
    0: input: 4449444c036d016c05dbb7017598abec810171ae9db1900171b99adecb0102aaacd9d0067d6e7101000101000000077469746c655f313f73366d35772d753337636b2d77667934662d78676c6c742d6a657268752d617833336d2d66726e35732d73617269352d736a6335642d376c37616e2d7861650109636f6e74656e745f32_80a0f096e0b5f002
       table: type table0 = vec table1
       type table1 = record {
         23_515 : int32;
         272_307_608 : text;
         302_796_462 : text;
         427_265_337 : table2;
         1_779_848_746 : nat;
       }
       type table2 = opt text
       wire_type: nat, expect_type: nat
    1: Internal error at /root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/candid-0.8.4/src/de.rs:548. Please file a bug.

This works:

#[derive(CandidType, Debug, Serialize, Deserialize)]
pub struct Suggection2 {
    pub id: i32,
    pub title: String,
    pub content: Option<String>,
    pub principal: String,
    pub created_at: u128,
}

#[test]
fn test_candid_decode() {
    let vecc: Vec<u8> = vec![
        68, 73, 68, 76, 3, 109, 1, 108, 5, 219, 183, 1, 117, 152, 171, 236, 129, 1, 113, 174, 157,
        177, 144, 1, 113, 185, 154, 222, 203, 1, 2, 170, 172, 217, 208, 6, 125, 110, 113, 1, 0, 1,
        1, 0, 0, 0, 7, 116, 105, 116, 108, 101, 95, 49, 63, 115, 54, 109, 53, 119, 45, 117, 51, 55,
        99, 107, 45, 119, 102, 121, 52, 102, 45, 120, 103, 108, 108, 116, 45, 106, 101, 114, 104,
        117, 45, 97, 120, 51, 51, 109, 45, 102, 114, 110, 53, 115, 45, 115, 97, 114, 105, 53, 45,
        115, 106, 99, 53, 100, 45, 55, 108, 55, 97, 110, 45, 120, 97, 101, 1, 9, 99, 111, 110, 116,
        101, 110, 116, 95, 50, 128, 160, 240, 150, 224, 181, 240, 2,
    ];
    let res: Result<(Vec<Suggection2>,), candid::Error> = candid::decode_args(&vecc);
    println!("test_candid_decode: {:?}", res);

    assert!(res.is_ok());
}