summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_meta/src/reader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_meta/src/reader.rs')
-rw-r--r--third_party/rust/uniffi_meta/src/reader.rs148
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:?}"),
- }))
+ })
}
}