-
Couldn't load subscription status.
- Fork 100
feat: impl ReaderBuilder
#1465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: impl ReaderBuilder
#1465
Changes from all commits
44d8faa
e509d31
2a39a23
73aead9
296aa51
ffd8015
de83d42
5e638e8
b5093a4
023fde2
427c7e1
d3a078f
eb40a9f
ae3aee6
929a396
899b0ab
fbe8976
c4e255c
3a4d500
68ba524
fce4aa8
beecb93
81efbdc
3da6b20
c3de5a0
4608f62
8941f2c
4f6e63f
913172d
eead715
efdae9f
31c9dc6
953e690
7f9e282
c3eb1ca
7192282
8296652
c480a42
310ebd1
e21b6ac
24538a7
b937db4
eb2477c
bd3d3e4
e58780a
eb170fd
93ece88
230e36c
dd5c69e
c0e6783
f196ae1
0122490
5724172
29116b8
07e826a
e974cea
39544ef
d8a2881
fd4edee
118640d
2fed088
434938a
1c7cb74
3607330
3ac02b0
d603795
1d4f8d6
924af31
263e13d
0268023
98222b5
45e165f
f3352bf
b0bf042
1653c4f
350f946
9be45f6
42057d5
10b2f6a
9551bcf
b2c687f
9f2cb0c
ff0b160
4d6fb4d
07dedf9
779c1fe
4e605d0
7aeb9c3
269fa8f
a253d21
9c4c34d
6cd520b
ba61dd0
18a9ccc
8a50921
756011f
e8f1c12
76a7523
70e49f4
dbe0d34
984bb2f
c3fb701
3b7685c
118e497
80333d8
65a58bd
9de74d0
a04ce76
b7bbc73
11c5a06
4cae259
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,7 @@ use serde_with::skip_serializing_none; | |
| #[cfg(feature = "file_io")] | ||
| use crate::utils::io_utils::uri_to_path; | ||
| use crate::{ | ||
| asset_io::CAIRead, | ||
| crypto::base64, | ||
| dynamic_assertion::PartialClaim, | ||
| error::{Error, Result}, | ||
|
|
@@ -72,6 +73,173 @@ pub trait AsyncPostValidator { | |
| ) -> Result<Option<Value>>; | ||
| } | ||
|
|
||
| pub struct ReaderBuilder { | ||
| settings: Settings, | ||
| external_manifest: Option<Box<dyn CAIRead>>, | ||
|
Comment on lines
+76
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this could be done as a ReaderAsset and include format and stream. then we can call something like this on Reader |
||
| fragments: Option<Vec<Box<dyn CAIRead>>>, | ||
| } | ||
|
|
||
| impl ReaderBuilder { | ||
| pub fn new() -> Self { | ||
| Self { | ||
| settings: Settings::default(), | ||
| external_manifest: None, | ||
| fragments: None, | ||
| } | ||
| } | ||
|
|
||
| pub fn with_settings(settings: Settings) -> Self { | ||
| Self { | ||
| settings, | ||
| external_manifest: None, | ||
| fragments: None, | ||
| } | ||
| } | ||
|
|
||
| pub fn external_manifest( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be set_external_manifest(), otherwise it looks like a getter in Rust. |
||
| mut self, | ||
| external_manifest: impl Read + Seek + Send + 'static, | ||
| ) -> Self { | ||
| self.external_manifest = Some(Box::new(external_manifest)); | ||
| self | ||
| } | ||
|
|
||
| pub fn add_fragment(mut self, fragment: impl Read + Seek + Send + 'static) -> Self { | ||
| let fragments = self.fragments.get_or_insert_default(); | ||
| fragments.push(Box::new(fragment)); | ||
| self | ||
| } | ||
|
|
||
| // TODO: | ||
| // pub fn http_resolver(self, resolver: impl SyncHttpResolver) -> Self { | ||
| // todo!() | ||
| // } | ||
|
|
||
| #[async_generic] | ||
| pub fn build(self, format: &str, mut stream: impl Read + Seek + Send) -> Result<Reader> { | ||
| match self.fragments { | ||
| Some(mut fragments) => { | ||
| match self.external_manifest { | ||
| Some(mut external_manifest) => { | ||
| // TODO: internally we actually convert c2pa_data to a stream again, we should modify the function | ||
| // signatures to stream by default | ||
| let mut c2pa_data = Vec::new(); | ||
| external_manifest.read_to_end(&mut c2pa_data)?; | ||
|
|
||
| let mut validation_log = StatusTracker::default(); | ||
| if _sync { | ||
| let store = Store::from_manifest_data_and_stream_and_fragments( | ||
| &c2pa_data, | ||
| format, | ||
| &mut stream, | ||
| &mut fragments, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| )?; | ||
| Reader::from_store(store, &mut validation_log, &self.settings) | ||
| } else { | ||
| let store = Store::from_manifest_data_and_stream_and_fragments_async( | ||
| &c2pa_data, | ||
| format, | ||
| &mut stream, | ||
| &mut fragments, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| ) | ||
| .await?; | ||
| Reader::from_store_async(store, &mut validation_log, &self.settings) | ||
| .await | ||
| } | ||
| } | ||
| None => { | ||
| let mut validation_log = StatusTracker::default(); | ||
| if _sync { | ||
| let store = Store::load_fragments_from_stream( | ||
| format, | ||
| &mut stream, | ||
| &mut fragments, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| )?; | ||
| Reader::from_store(store, &mut validation_log, &self.settings) | ||
| } else { | ||
| let store = Store::load_fragments_from_stream_async( | ||
| format, | ||
| &mut stream, | ||
| &mut fragments, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| ) | ||
| .await?; | ||
| Reader::from_store_async(store, &mut validation_log, &self.settings) | ||
| .await | ||
| } | ||
| } | ||
| } | ||
| } | ||
| None => match self.external_manifest { | ||
| Some(mut external_manifest) => { | ||
| // TODO: internally we actually convert c2pa_data to a stream again, we should modify the function | ||
| // signatures to stream by default | ||
| let mut c2pa_data = Vec::new(); | ||
| external_manifest.read_to_end(&mut c2pa_data)?; | ||
|
|
||
| let mut validation_log = StatusTracker::default(); | ||
| if _sync { | ||
| let store = Store::from_manifest_data_and_stream( | ||
| &c2pa_data, | ||
| format, | ||
| stream, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| )?; | ||
| Reader::from_store(store, &mut validation_log, &self.settings) | ||
| } else { | ||
| let store = Store::from_manifest_data_and_stream_async( | ||
| &c2pa_data, | ||
| format, | ||
| stream, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| ) | ||
| .await?; | ||
| Reader::from_store_async(store, &mut validation_log, &self.settings).await | ||
| } | ||
| } | ||
| None => { | ||
| let mut validation_log = StatusTracker::default(); | ||
| if _sync { | ||
| let store = Store::from_stream( | ||
| format, | ||
| &mut stream, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| )?; | ||
| Reader::from_store(store, &mut validation_log, &self.settings) | ||
| } else { | ||
| let store = Store::from_stream_async( | ||
| format, | ||
| &mut stream, | ||
| self.settings.verify.verify_after_reading, | ||
| &mut validation_log, | ||
| &self.settings, | ||
| ) | ||
| .await?; | ||
| Reader::from_store_async(store, &mut validation_log, &self.settings).await | ||
| } | ||
| } | ||
| }, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Use a Reader to read and validate a manifest store. | ||
| #[skip_serializing_none] | ||
| #[derive(Serialize, Deserialize)] | ||
|
|
@@ -359,10 +527,15 @@ impl Reader { | |
|
|
||
| let mut init_segment = std::fs::File::open(path.as_ref())?; | ||
|
|
||
| match Store::load_from_file_and_fragments( | ||
| let mut fragments: Vec<Box<dyn CAIRead>> = fragments | ||
| .iter() | ||
| .map(|path| File::open(path).map(|file| Box::new(file) as Box<dyn CAIRead>)) | ||
| .collect::<Result<_, std::io::Error>>()?; | ||
|
|
||
| match Store::load_fragments_from_stream( | ||
| &asset_type, | ||
| &mut init_segment, | ||
| fragments, | ||
| &mut fragments, | ||
| verify, | ||
| &mut validation_log, | ||
| &settings, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formulation may be necessary, given the iteration you're doing at line 851, but it reads as you'll be changing the membership of
fragment_pathsrather than you need mutable access to eachfragment_stream.I wonder if there's a way to convey that distinction in meaning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can store a mutable reference to each stream in the slice although I suspect that would be much more inconvenient than passing a mutable reference to the collection. Let's say you had an owned vec of files, you would have to allocate a new vec that stores mutable references to them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose you would still have to box them anyways, but I think ideally we'd have a generic here so they don't need to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are generally moving away from CaiRead and CaiWrite as we don't need them anymore. But since this function already uses CAIRead, I think this is ok here.