iceberg/spec/manifest/
metadata.rs1use std::collections::HashMap;
19use std::sync::Arc;
20
21use typed_builder::TypedBuilder;
22
23use super::{FormatVersion, ManifestContentType, PartitionSpec, Schema};
24use crate::error::{Result, invalid_data};
25use crate::spec::{PartitionField, SchemaId, SchemaRef};
26
27#[derive(Debug, PartialEq, Clone, Eq, TypedBuilder)]
29pub struct ManifestMetadata {
30 pub schema: SchemaRef,
33 pub schema_id: SchemaId,
35 pub partition_spec: PartitionSpec,
37 pub format_version: FormatVersion,
39 pub content: ManifestContentType,
41}
42
43impl ManifestMetadata {
44 pub fn parse(meta: &HashMap<String, Vec<u8>>) -> Result<Self> {
46 let schema = Arc::new({
47 let bs = meta.get("schema").ok_or_else(|| {
48 invalid_data!("schema is required in manifest metadata but not found")
49 })?;
50 serde_json::from_slice::<Schema>(bs).map_err(|err| {
51 invalid_data!("Fail to parse schema in manifest metadata").with_source(err)
52 })?
53 });
54 let schema_id: i32 = meta
55 .get("schema-id")
56 .map(|bs| {
57 String::from_utf8_lossy(bs).parse().map_err(|err| {
58 invalid_data!("Fail to parse schema id in manifest metadata").with_source(err)
59 })
60 })
61 .transpose()?
62 .unwrap_or(0);
63 let partition_spec = {
64 let fields = {
65 let bs = meta.get("partition-spec").ok_or_else(|| {
66 invalid_data!("partition-spec is required in manifest metadata but not found")
67 })?;
68 serde_json::from_slice::<Vec<PartitionField>>(bs).map_err(|err| {
69 invalid_data!("Fail to parse partition spec in manifest metadata")
70 .with_source(err)
71 })?
72 };
73 let spec_id = meta
74 .get("partition-spec-id")
75 .map(|bs| {
76 String::from_utf8_lossy(bs).parse().map_err(|err| {
77 invalid_data!("Fail to parse partition spec id in manifest metadata")
78 .with_source(err)
79 })
80 })
81 .transpose()?
82 .unwrap_or(0);
83 PartitionSpec::builder(schema.clone())
84 .with_spec_id(spec_id)
85 .add_unbound_fields(fields.into_iter().map(|f| f.into_unbound()))?
86 .build()?
87 };
88 let format_version = if let Some(bs) = meta.get("format-version") {
89 serde_json::from_slice::<FormatVersion>(bs).map_err(|err| {
90 invalid_data!("Fail to parse format version in manifest metadata").with_source(err)
91 })?
92 } else {
93 FormatVersion::V1
94 };
95 let content = if let Some(v) = meta.get("content") {
96 let v = String::from_utf8_lossy(v);
97 v.parse()?
98 } else {
99 ManifestContentType::Data
100 };
101 Ok(ManifestMetadata {
102 schema,
103 schema_id,
104 partition_spec,
105 format_version,
106 content,
107 })
108 }
109
110 pub fn schema(&self) -> &SchemaRef {
112 &self.schema
113 }
114
115 pub fn schema_id(&self) -> SchemaId {
117 self.schema_id
118 }
119
120 pub fn partition_spec(&self) -> &PartitionSpec {
122 &self.partition_spec
123 }
124
125 pub fn format_version(&self) -> &FormatVersion {
127 &self.format_version
128 }
129
130 pub fn content(&self) -> &ManifestContentType {
132 &self.content
133 }
134}