Skip to content

Commit e1d4b5c

Browse files
committed
Introduce atrium_api::types::Unknown for unknown fields
Closes sugyan#204.
1 parent 75673d0 commit e1d4b5c

File tree

12 files changed

+68
-22
lines changed

12 files changed

+68
-22
lines changed

atrium-api/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- `atrium_api::types::Unknown`
11+
12+
### Changed
13+
- `unknown` field types that don't have a well-known format now have the type
14+
`atrium_api::types::Unknown` instead of `atrium_api::records::Record`.
15+
916
## [0.23.2](https://github.com/sugyan/atrium/compare/atrium-api-v0.23.1...atrium-api-v0.23.2) - 2024-07-03
1017

1118
### Added

atrium-api/src/app/bsky/embed/record.rs

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/identity/get_recommended_did_credentials.rs

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/identity/sign_plc_operation.rs

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/identity/submit_plc_operation.rs

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/repo/apply_writes.rs

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/repo/get_record.rs

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/repo/list_records.rs

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/com/atproto/server/create_account.rs

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/tools/ozone/moderation/defs.rs

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

atrium-api/src/types.rs

+26
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ pub enum Union<T> {
128128
Unknown(UnknownData),
129129
}
130130

131+
/// Data with an unknown schema in an open [`Union`].
132+
///
131133
/// The data of variants represented by a map and include a `$type` field indicating the variant type.
132134
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
133135
pub struct UnknownData {
@@ -137,6 +139,30 @@ pub struct UnknownData {
137139
pub data: Ipld,
138140
}
139141

142+
/// Arbitrary data with no specific validation and no type-specific fields.
143+
///
144+
/// Corresponds to [the `unknown` field type].
145+
///
146+
/// [the `unknown` field type]: https://atproto.com/specs/lexicon#unknown
147+
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
148+
#[serde(try_from = "Ipld")]
149+
pub struct Unknown {
150+
pub data: Ipld,
151+
}
152+
153+
impl TryFrom<Ipld> for Unknown {
154+
type Error = &'static str;
155+
156+
fn try_from(value: Ipld) -> Result<Self, Self::Error> {
157+
// Enforce the ATProto data model.
158+
// https://atproto.com/specs/data-model
159+
match value {
160+
Ipld::Float(_) => Err("Floats are not allowed in ATProto"),
161+
data => Ok(Unknown { data }),
162+
}
163+
}
164+
}
165+
140166
#[cfg(test)]
141167
mod tests {
142168
use super::*;

lexicon/atrium-codegen/src/token_stream.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ fn lex_object_property(
320320
LexObjectProperty::Boolean(boolean) => boolean_type(boolean)?,
321321
LexObjectProperty::Integer(integer) => integer_type(integer)?,
322322
LexObjectProperty::String(string) => string_type(string)?,
323-
LexObjectProperty::Unknown(unknown) => unknown_type(unknown, Some(name))?,
323+
LexObjectProperty::Unknown(unknown) => unknown_type(unknown, NamedUnknown::Field(name))?,
324324
};
325325
let field_name = format_ident!(
326326
"{}",
@@ -401,7 +401,7 @@ fn array_type(
401401
let (_, item_type) = match &array.items {
402402
LexArrayItem::Integer(integer) => integer_type(integer)?,
403403
LexArrayItem::String(string) => string_type(string)?,
404-
LexArrayItem::Unknown(unknown) => unknown_type(unknown, None)?,
404+
LexArrayItem::Unknown(unknown) => unknown_type(unknown, NamedUnknown::Array(name))?,
405405
LexArrayItem::CidLink(cid_link) => cid_link_type(cid_link)?,
406406
LexArrayItem::Ref(r#ref) => ref_type(r#ref)?,
407407
LexArrayItem::Union(union) => union_type(
@@ -562,13 +562,26 @@ fn string_type(string: &LexString) -> Result<(TokenStream, TokenStream)> {
562562
Ok((description, typ))
563563
}
564564

565-
fn unknown_type(unknown: &LexUnknown, name: Option<&str>) -> Result<(TokenStream, TokenStream)> {
565+
enum NamedUnknown<'s> {
566+
Field(&'s str),
567+
Array(&'s str),
568+
}
569+
570+
fn unknown_type(
571+
unknown: &LexUnknown,
572+
name: NamedUnknown<'_>,
573+
) -> Result<(TokenStream, TokenStream)> {
566574
let description = description(&unknown.description);
567-
if name == Some("didDoc") {
568-
Ok((description, quote!(crate::did_doc::DidDocument)))
569-
} else {
570-
Ok((description, quote!(crate::records::Record)))
571-
}
575+
576+
let typ = match name {
577+
NamedUnknown::Field("didDoc") => quote!(crate::did_doc::DidDocument),
578+
NamedUnknown::Field("record") | NamedUnknown::Array("relatedRecords") => {
579+
quote!(crate::records::Record)
580+
}
581+
_ => quote!(crate::types::Unknown),
582+
};
583+
584+
Ok((description, typ))
572585
}
573586

574587
fn description(description: &Option<String>) -> TokenStream {

0 commit comments

Comments
 (0)