diff options
Diffstat (limited to 'third_party/rust/uniffi_meta/src/reader.rs')
-rw-r--r-- | third_party/rust/uniffi_meta/src/reader.rs | 148 |
1 files changed, 120 insertions, 28 deletions
diff --git a/third_party/rust/uniffi_meta/src/reader.rs b/third_party/rust/uniffi_meta/src/reader.rs index bf6525f2b5..6fec6cb3a3 100644 --- a/third_party/rust/uniffi_meta/src/reader.rs +++ b/third_party/rust/uniffi_meta/src/reader.rs @@ -52,9 +52,10 @@ impl<'a> MetadataReader<'a> { codes::CONSTRUCTOR => self.read_constructor()?.into(), codes::METHOD => self.read_method()?.into(), codes::RECORD => self.read_record()?.into(), - codes::ENUM => self.read_enum(false)?.into(), - codes::ERROR => self.read_error()?.into(), - codes::INTERFACE => self.read_object()?.into(), + codes::ENUM => self.read_enum()?.into(), + codes::INTERFACE => self.read_object(ObjectImpl::Struct)?.into(), + codes::TRAIT_INTERFACE => self.read_object(ObjectImpl::Trait)?.into(), + codes::CALLBACK_TRAIT_INTERFACE => self.read_object(ObjectImpl::CallbackTrait)?.into(), codes::CALLBACK_INTERFACE => self.read_callback_interface()?.into(), codes::TRAIT_METHOD => self.read_trait_method()?.into(), codes::UNIFFI_TRAIT => self.read_uniffi_trait()?.into(), @@ -80,6 +81,17 @@ impl<'a> MetadataReader<'a> { } } + fn read_u16(&mut self) -> Result<u16> { + if self.buf.len() >= 2 { + // read the value as little-endian + let value = u16::from_le_bytes([self.buf[0], self.buf[1]]); + self.buf = &self.buf[2..]; + Ok(value) + } else { + bail!("Not enough data left in buffer to read a u16 value"); + } + } + fn read_u32(&mut self) -> Result<u32> { if self.buf.len() >= 4 { // read the value as little-endian @@ -105,6 +117,17 @@ impl<'a> MetadataReader<'a> { String::from_utf8(slice.into()).context("Invalid string data") } + fn read_long_string(&mut self) -> Result<String> { + let size = self.read_u16()? as usize; + let slice; + (slice, self.buf) = self.buf.split_at(size); + String::from_utf8(slice.into()).context("Invalid string data") + } + + fn read_optional_long_string(&mut self) -> Result<Option<String>> { + Ok(Some(self.read_long_string()?).filter(|str| !str.is_empty())) + } + fn read_type(&mut self) -> Result<Type> { let value = self.read_u8()?; Ok(match value { @@ -122,7 +145,6 @@ impl<'a> MetadataReader<'a> { codes::TYPE_STRING => Type::String, codes::TYPE_DURATION => Type::Duration, codes::TYPE_SYSTEM_TIME => Type::Timestamp, - codes::TYPE_FOREIGN_EXECUTOR => Type::ForeignExecutor, codes::TYPE_RECORD => Type::Record { module_path: self.read_string()?, name: self.read_string()?, @@ -134,7 +156,17 @@ impl<'a> MetadataReader<'a> { codes::TYPE_INTERFACE => Type::Object { module_path: self.read_string()?, name: self.read_string()?, - imp: ObjectImpl::from_is_trait(self.read_bool()?), + imp: ObjectImpl::Struct, + }, + codes::TYPE_TRAIT_INTERFACE => Type::Object { + module_path: self.read_string()?, + name: self.read_string()?, + imp: ObjectImpl::Trait, + }, + codes::TYPE_CALLBACK_TRAIT_INTERFACE => Type::Object { + module_path: self.read_string()?, + name: self.read_string()?, + imp: ObjectImpl::CallbackTrait, }, codes::TYPE_CALLBACK_INTERFACE => Type::CallbackInterface { module_path: self.read_string()?, @@ -198,6 +230,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(FnMetadata { module_path, name, @@ -205,6 +238,7 @@ impl<'a> MetadataReader<'a> { inputs, return_type, throws, + docstring, checksum: self.calc_checksum(), }) } @@ -213,8 +247,10 @@ impl<'a> MetadataReader<'a> { let module_path = self.read_string()?; let self_name = self.read_string()?; let name = self.read_string()?; + let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; return_type .filter(|t| { @@ -228,10 +264,12 @@ impl<'a> MetadataReader<'a> { Ok(ConstructorMetadata { module_path, self_name, + is_async, name, inputs, throws, checksum: self.calc_checksum(), + docstring, }) } @@ -242,6 +280,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(MethodMetadata { module_path, self_name, @@ -252,6 +291,7 @@ impl<'a> MetadataReader<'a> { throws, takes_self_by_arc: false, // not emitted by macros checksum: self.calc_checksum(), + docstring, }) } @@ -260,13 +300,25 @@ impl<'a> MetadataReader<'a> { module_path: self.read_string()?, name: self.read_string()?, fields: self.read_fields()?, + docstring: self.read_optional_long_string()?, }) } - fn read_enum(&mut self, is_flat_error: bool) -> Result<EnumMetadata> { + fn read_enum(&mut self) -> Result<EnumMetadata> { let module_path = self.read_string()?; let name = self.read_string()?; - let variants = if is_flat_error { + let forced_flatness = match self.read_u8()? { + 0 => None, + 1 => Some(false), + 2 => Some(true), + _ => unreachable!("invalid flatness"), + }; + let discr_type = if self.read_bool()? { + Some(self.read_type()?) + } else { + None + }; + let variants = if forced_flatness == Some(true) { self.read_flat_variants()? } else { self.read_variants()? @@ -275,21 +327,20 @@ impl<'a> MetadataReader<'a> { Ok(EnumMetadata { module_path, name, + forced_flatness, + discr_type, variants, + non_exhaustive: self.read_bool()?, + docstring: self.read_optional_long_string()?, }) } - fn read_error(&mut self) -> Result<ErrorMetadata> { - let is_flat = self.read_bool()?; - let enum_ = self.read_enum(is_flat)?; - Ok(ErrorMetadata::Enum { enum_, is_flat }) - } - - fn read_object(&mut self) -> Result<ObjectMetadata> { + fn read_object(&mut self, imp: ObjectImpl) -> Result<ObjectMetadata> { Ok(ObjectMetadata { module_path: self.read_string()?, name: self.read_string()?, - imp: ObjectImpl::from_is_trait(self.read_bool()?), + imp, + docstring: self.read_optional_long_string()?, }) } @@ -322,6 +373,7 @@ impl<'a> MetadataReader<'a> { Ok(CallbackInterfaceMetadata { module_path: self.read_string()?, name: self.read_string()?, + docstring: self.read_optional_long_string()?, }) } @@ -333,6 +385,7 @@ impl<'a> MetadataReader<'a> { let is_async = self.read_bool()?; let inputs = self.read_inputs()?; let (return_type, throws) = self.read_return_type()?; + let docstring = self.read_optional_long_string()?; Ok(TraitMethodMetadata { module_path, trait_name, @@ -344,6 +397,7 @@ impl<'a> MetadataReader<'a> { throws, takes_self_by_arc: false, // not emitted by macros checksum: self.calc_checksum(), + docstring, }) } @@ -353,8 +407,13 @@ impl<'a> MetadataReader<'a> { .map(|_| { let name = self.read_string()?; let ty = self.read_type()?; - let default = self.read_default(&name, &ty)?; - Ok(FieldMetadata { name, ty, default }) + let default = self.read_optional_default(&name, &ty)?; + Ok(FieldMetadata { + name, + ty, + default, + docstring: self.read_optional_long_string()?, + }) }) .collect() } @@ -365,7 +424,9 @@ impl<'a> MetadataReader<'a> { .map(|_| { Ok(VariantMetadata { name: self.read_string()?, + discr: self.read_optional_default("<variant-value>", &Type::UInt64)?, fields: self.read_fields()?, + docstring: self.read_optional_long_string()?, }) }) .collect() @@ -377,7 +438,9 @@ impl<'a> MetadataReader<'a> { .map(|_| { Ok(VariantMetadata { name: self.read_string()?, + discr: None, fields: vec![], + docstring: self.read_optional_long_string()?, }) }) .collect() @@ -387,13 +450,16 @@ impl<'a> MetadataReader<'a> { let len = self.read_u8()?; (0..len) .map(|_| { + let name = self.read_string()?; + let ty = self.read_type()?; + let default = self.read_optional_default(&name, &ty)?; Ok(FnParamMetadata { - name: self.read_string()?, - ty: self.read_type()?, + name, + ty, + default, // not emitted by macros by_ref: false, optional: false, - default: None, }) }) .collect() @@ -405,14 +471,18 @@ impl<'a> MetadataReader<'a> { Some(checksum_metadata(metadata_buf)) } - fn read_default(&mut self, name: &str, ty: &Type) -> Result<Option<LiteralMetadata>> { - let has_default = self.read_bool()?; - if !has_default { - return Ok(None); + fn read_optional_default(&mut self, name: &str, ty: &Type) -> Result<Option<LiteralMetadata>> { + if self.read_bool()? { + Ok(Some(self.read_default(name, ty)?)) + } else { + Ok(None) } + } + fn read_default(&mut self, name: &str, ty: &Type) -> Result<LiteralMetadata> { let literal_kind = self.read_u8()?; - Ok(Some(match literal_kind { + + Ok(match literal_kind { codes::LIT_STR => { ensure!( matches!(ty, Type::String), @@ -422,12 +492,24 @@ impl<'a> MetadataReader<'a> { } codes::LIT_INT => { let base10_digits = self.read_string()?; + // procmacros emit the type for discriminant values based purely on whether the constant + // is positive or negative. + let ty = if !base10_digits.is_empty() + && base10_digits.as_bytes()[0] == b'-' + && ty == &Type::UInt64 + { + &Type::Int64 + } else { + ty + }; macro_rules! parse_int { ($ty:ident, $variant:ident) => { LiteralMetadata::$variant( base10_digits .parse::<$ty>() - .with_context(|| format!("parsing default for field {name}"))? + .with_context(|| { + format!("parsing default for field {name}: {base10_digits}") + })? .into(), Radix::Decimal, ty.to_owned(), @@ -458,8 +540,18 @@ impl<'a> MetadataReader<'a> { } }, codes::LIT_BOOL => LiteralMetadata::Boolean(self.read_bool()?), - codes::LIT_NULL => LiteralMetadata::Null, + codes::LIT_NONE => match ty { + Type::Optional { .. } => LiteralMetadata::None, + _ => bail!("field {name} of type {ty:?} can't have a default value of None"), + }, + codes::LIT_SOME => match ty { + Type::Optional { inner_type, .. } => LiteralMetadata::Some { + inner: Box::new(self.read_default(name, inner_type)?), + }, + _ => bail!("field {name} of type {ty:?} can't have a default value of None"), + }, + codes::LIT_EMPTY_SEQ => LiteralMetadata::EmptySequence, _ => bail!("Unexpected literal kind code: {literal_kind:?}"), - })) + }) } } |