repo_description: Empowering everyone to build reliable and efficient software.
repo_topics: compiler language rust
code: use super::*;
  
  #[test]
  fn test_struct_info_roundtrip() {
      let s = ItemEnum::Struct(Struct {
          generics: Generics { params: vec![], where_predicates: vec![] },
          kind: StructKind::Plain { fields: vec![], has_stripped_fields: false },
          impls: vec![],
      });
  
      // JSON
      let struct_json = serde_json::to_string(&s).unwrap();
      let de_s = serde_json::from_str(&struct_json).unwrap();
      assert_eq!(s, de_s);
  
      // Bincode
      let encoded: Vec<u8> = bincode::serialize(&s).unwrap();
      let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
      assert_eq!(s, decoded);
  }
  
  #[test]
  fn test_union_info_roundtrip() {
      let u = ItemEnum::Union(Union {
          generics: Generics { params: vec![], where_predicates: vec![] },
          has_stripped_fields: false,
          fields: vec![],
          impls: vec![],
      });
  
      // JSON
      let union_json = serde_json::to_string(&u).unwrap();
      let de_u = serde_json::from_str(&union_json).unwrap();
      assert_eq!(u, de_u);
  
      // Bincode
      let encoded: Vec<u8> = bincode::serialize(&u).unwrap();
      let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
      assert_eq!(u, decoded);
  }
  
  #[cfg(feature = "rkyv_0_8")]
  mod rkyv {
      use std::fmt::Debug;
  
      use rkyv::Archive;
      use rkyv::api::high::{HighDeserializer, HighSerializer};
      use rkyv::bytecheck::CheckBytes;
      use rkyv::rancor::Strategy;
      use rkyv::ser::allocator::ArenaHandle;
      use rkyv::util::AlignedVec;
      use rkyv::validation::Validator;
      use rkyv::validation::archive::ArchiveValidator;
      use rkyv::validation::shared::SharedValidator;
  
      use crate::*;
  
      #[test]
      /// A test to exercise the (de)serialization roundtrip for a representative selection of types,
      /// covering most of the rkyv-specific attributes we had to had.
      fn test_rkyv_roundtrip() {
          // Standard derives: a plain struct and union, mirroring the existing serde/bincode tests.
          let s = ItemEnum::Struct(Struct {
              generics: Generics { params: vec![], where_predicates: vec![] },
              kind: StructKind::Plain { fields: vec![Id(1), Id(2)], has_stripped_fields: false },
              impls: vec![Id(3)],
          });
          rkyv_roundtrip(&s);
  
          let u = ItemEnum::Union(Union {
              generics: Generics { params: vec![], where_predicates: vec![] },
              has_stripped_fields: false,
              fields: vec![Id(1)],
              impls: vec![],
          });
          rkyv_roundtrip(&u);
  
          // Extra trait derives, via rkyv(derive(PartialEq, Eq, PartialOrd, Ord, Hash)), on the archived type.
          rkyv_roundtrip(&Id(99));
  
          // Recursive cycle-breaking: `BorrowedRef` has omit_bounds on its `Box<Type>` field.
          let ty = Type::BorrowedRef {
              lifetime: Some("'a".to_string()),
              is_mutable: false,
              type_: Box::new(Type::Primitive("str".to_string())),
          };
          rkyv_roundtrip(&ty);
  
          // `Slice` and `Tuple` are tuple-variant fields with omit_bounds on the unnamed field,
          // which required special syntax (attribute inside the parentheses) to compile.
          let ty = Type::Slice(Box::new(Type::Tuple(vec![
              Type::Primitive("u32".to_string()),
              Type::Generic("T".to_string()),
          ])));
          rkyv_roundtrip(&ty);
  
          // `Path` has serialize_bounds/deserialize_bounds and omit_bounds on its `args` field.
          // `GenericArgs::AngleBracketed` exercises the full recursive chain: `Path` -> `GenericArgs` -> `GenericArg` -> `Type`.
          let path = Path {
              path: "std::option::Option".to_string(),
              id: Id(42),
              args: Some(Box::new(GenericArgs::AngleBracketed {
                  args: vec![GenericArg::Type(Type::Primitive("u32".to_string()))],
                  constraints: vec![],
              })),
          };
          rkyv_roundtrip(&path);
  
          // `FunctionPointer` is a `Box<FunctionPointer>` behind `omit_bounds` in `Type`.
          // It transitively contains `Type` via `FunctionSignature`, exercising the cycle from the other direction.
          let fp = Type::FunctionPointer(Box::new(FunctionPointer {
              sig: FunctionSignature {
                  inputs: vec![("x".to_string(), Type::Primitive("i32".to_string()))],
                  output: Some(Type::Primitive("bool".to_string())),
                  is_c_variadic: false,
              },
              generic_params: vec![],
              header: FunctionHeader {
                  is_const: false,
                  is_unsafe: false,
                  is_async: false,
                  abi: Abi::Rust,
              },
          }));
          rkyv_roundtrip(&fp);
      }
  
      /// A helper function for roundtrip testing of rkyv-powered deserialization.
      fn rkyv_roundtrip<T>(value: &T)
      where
          T: PartialEq
              + Debug
              + Archive
              + for<'a> rkyv::Serialize<
                  HighSerializer<AlignedVec, ArenaHandle<'a>, rkyv::rancor::Error>,
              >,
          T::Archived: rkyv::Deserialize<T, HighDeserializer<rkyv::rancor::Error>>
              + Debug
              + for<'a> CheckBytes<
                  Strategy<Validator<ArchiveValidator<'a>, SharedValidator>, rkyv::rancor::Error>,
              >,
      {
          let bytes =
              rkyv::api::high::to_bytes_in::<_, rkyv::rancor::Error>(value, AlignedVec::new())
                  .unwrap();
          let archived = rkyv::api::high::access::<T::Archived, rkyv::rancor::Error>(&bytes)
              .expect("Failed to access archived data");
          let deserialized: T = rkyv::api::deserialize_using::<_, _, rkyv::rancor::Error>(
              archived,
              &mut rkyv::de::Pool::new(),
          )
          .unwrap();
          assert_eq!(value, &deserialized);
      }
  }
  