diff --git a/Cargo.lock b/Cargo.lock index 721c69f..22af1d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,6 +96,7 @@ dependencies = [ "iota-crypto", "itertools", "mime", + "protobuf", "ureq", "webp", ] @@ -547,6 +548,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee4a7d8b91800c8f167a6268d1a1026607368e1adc84e98fe044aeb905302f7" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-support" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca157fe12fc7ee2e315f2f735e27df41b3d97cdd70ea112824dac1ffb08ee1c" +dependencies = [ + "thiserror", +] + [[package]] name = "quote" version = "1.0.21" @@ -633,6 +654,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tiff" version = "0.7.3" diff --git a/Cargo.toml b/Cargo.toml index ae8e562..e3029b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ itertools = "0.10.3" blurhash = "0.1.1" base64 = "0.13.0" mime = "0.3.16" +protobuf = "3.1.0" [dependencies.iota-crypto] version = "0.13.0" diff --git a/protobuf/image.proto b/protobuf/image.proto new file mode 100644 index 0000000..26e1c83 --- /dev/null +++ b/protobuf/image.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +message Image { + bytes key = 1; + string full_url = 2; + string thumb_url = 3; + string blurhash = 4; +} diff --git a/protobuf/index.proto b/protobuf/index.proto new file mode 100644 index 0000000..467ff58 --- /dev/null +++ b/protobuf/index.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +import "image.proto"; + +message Index { + repeated Image images = 1; + optional string title = 2; + optional string desc = 3; +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..5be540b --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,94 @@ +use std::{path::{PathBuf, Path}, io}; + +#[derive(Debug)] +pub enum AviaryError { + /// One of the files passed by the user simply did not exist + /// + /// The attached path is the file which didn't exist + /// + /// Handling: Halt execution before any upload begins and alert the user of any + /// missing files. + FileDNE(PathBuf), + + /// The program lacks permission to read one of the images provided by the user + /// + /// Handling: Halt execution before any upload begins and alert the user of the issue + ReadPermissionDenied(PathBuf), + + /// There was an issue reading data from the disk + /// + /// Handling: Halt execution immediately and alert the user + StreamReadError(PathBuf, io::Error), + + /// One or more of the images wasn't correctly encoded + /// + /// Handling: Halt execution immediately and ask the user if they're sure the + /// provided file is an image. + ImageFormatError(PathBuf), + + /// The server is currently having some difficulties + /// + /// Represents a 5XX or 4XX error, as well as any transport error that doesn't seem + /// like it could stem from a network issue. + /// + /// Handling: Halt execution and alert the user that the server isn't working at the + /// minute, and ask them to try a different server or try again. + ServerError(String), + + /// Couldn't connect to the server + /// + /// Indicates that there was some network error which prevented the client from + /// reaching the server. + /// + /// Handling: Halt execution and ask the user to check that their computer is + /// connected to the internet, and is not having any DNS issues. + ConnectionError(String), + + /// The server URL provided by the user was invalid + /// + /// Handling: Halt execution and alert the user that the server url they provided was + /// invalid, including a couple examples + BadServerParameter, +} + +impl AviaryError { + pub fn from_open_error(e: io::ErrorKind, location: &Path) -> AviaryError { + match e { + io::ErrorKind::NotFound => AviaryError::FileDNE(location.to_owned()), + io::ErrorKind::PermissionDenied => AviaryError::ReadPermissionDenied(location.to_owned()), + _ => panic!( + "Received an error kind that should be impossible for {}: {:?}", + location.display(), + e + ) + } + } + + pub fn from_upload_error(err: ureq::Error) -> AviaryError { + match err { + ureq::Error::Status(code, msg) => AviaryError::ServerError( + format!("Error code {} received from server: {}", code, + msg.into_string().unwrap_or(String::new()))), + ureq::Error::Transport(transport) => match transport.kind() { + ureq::ErrorKind::InvalidUrl => + AviaryError::BadServerParameter, + ureq::ErrorKind::Dns => + AviaryError::ConnectionError( + format!("DNS issue: {}", transport.message().unwrap_or(""))), + ureq::ErrorKind::Io => + AviaryError::ConnectionError( + format!("IO issue: {}", transport.message().unwrap_or(""))), + ureq::ErrorKind::ConnectionFailed => + AviaryError::ConnectionError( + format!("Connection issue: {}", transport.message().unwrap_or(""))), + ureq::ErrorKind::TooManyRedirects => + AviaryError::ServerError("Too many redirects".to_owned()), + ureq::ErrorKind::BadHeader => + AviaryError::ServerError("Invalid header from server".to_owned()), + ureq::ErrorKind::BadStatus => + AviaryError::ServerError("Invalid status from server".to_owned()), + unk => panic!("Unexpected transport error kind {unk}:\n{transport}") + }, + } + } +} diff --git a/src/main.rs b/src/main.rs index f6eea77..d7e3e23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,64 +2,17 @@ mod parse; mod crypto; mod upload; mod thumbnailing; +mod protobuf; +mod errors; use std::borrow::Cow; -use std::io::{self, ErrorKind, Read}; +use std::io::Read; use std::fs::File; -use std::path::{PathBuf, Path}; +use std::path::Path; +use errors::AviaryError; use itertools::{Itertools, Either}; - -#[derive(Debug)] -enum AviaryError { - /// One of the files passed by the user simply did not exist - /// - /// The attached path is the file which didn't exist - /// - /// Handling: Halt execution before any upload begins and alert the user of any - /// missing files. - FileDNE(PathBuf), - - /// The program lacks permission to read one of the images provided by the user - /// - /// Handling: Halt execution before any upload begins and alert the user of the issue - ReadPermissionDenied(PathBuf), - - /// There was an issue reading data from the disk - /// - /// Handling: Halt execution immediately and alert the user - StreamReadError(PathBuf, io::Error), - - /// One or more of the images wasn't correctly encoded - /// - /// Handling: Halt execution immediately and ask the user if they're sure the - /// provided file is an image. - ImageFormatError(PathBuf), - - /// The server is currently having some difficulties - /// - /// Represents a 5XX or 4XX error, as well as any transport error that doesn't seem - /// like it could stem from a network issue. - /// - /// Handling: Halt execution and alert the user that the server isn't working at the - /// minute, and ask them to try a different server or try again. - ServerError(String), - - /// Couldn't connect to the server - /// - /// Indicates that there was some network error which prevented the client from - /// reaching the server. - /// - /// Handling: Halt execution and ask the user to check that their computer is - /// connected to the internet, and is not having any DNS issues. - ConnectionError(String), - - /// The server URL provided by the user was invalid - /// - /// Handling: Halt execution and alert the user that the server url they provided was - /// invalid, including a couple examples - BadServerParameter, -} +use ::protobuf::Message; fn trim_url<'a>(base_url: &str, url: &'a str) -> Option<&'a str> { if url.starts_with(base_url) { @@ -84,16 +37,8 @@ fn main() { .map(Path::new) .map(|path| File::open(path) .map(|file| (path, file)) - .map_err(|e| match e.kind() { - ErrorKind::NotFound => AviaryError::FileDNE(path.to_owned()), - ErrorKind::PermissionDenied => AviaryError::ReadPermissionDenied(path.to_owned()), - _ => panic!( - "Received an error kind that should be impossible for {}: {:?}", - path.display(), - e - ) - } - )) + .map_err(|e| AviaryError::from_open_error(e.kind(), &path)) + ) .partition_result(); if !errors.is_empty() { @@ -119,7 +64,7 @@ fn main() { } else { Cow::Owned(format!("https://{}", args.server)) }; - let upload_records = files.into_iter() + let index_url = files.into_iter() .map(|(path, mut file)| (|| { let mut buff = Vec::with_capacity(file.metadata()?.len() as usize); @@ -146,31 +91,7 @@ fn main() { .and_then(|thumb_url| upload::put_data(&agent, &*full_server, &full_img) .map(|full_url| (key, full_url, thumb_url, blurhash))) - .map_err(|err| match err { - ureq::Error::Status(code, msg) => AviaryError::ServerError( - format!("Error code {} received from server: {}", code, - msg.into_string().unwrap_or(String::new()))), - ureq::Error::Transport(transport) => match transport.kind() { - ureq::ErrorKind::InvalidUrl => - AviaryError::BadServerParameter, - ureq::ErrorKind::Dns => - AviaryError::ConnectionError( - format!("DNS issue: {}", transport.message().unwrap_or(""))), - ureq::ErrorKind::Io => - AviaryError::ConnectionError( - format!("IO issue: {}", transport.message().unwrap_or(""))), - ureq::ErrorKind::ConnectionFailed => - AviaryError::ConnectionError( - format!("Connection issue: {}", transport.message().unwrap_or(""))), - ureq::ErrorKind::TooManyRedirects => - AviaryError::ServerError("Too many redirects".to_owned()), - ureq::ErrorKind::BadHeader => - AviaryError::ServerError("Invalid header from server".to_owned()), - ureq::ErrorKind::BadStatus => - AviaryError::ServerError("Invalid status from server".to_owned()), - unk => panic!("Unexpected transport error kind {unk}:\n{transport}") - }, - }) + .map_err(AviaryError::from_upload_error) )) .map(|r| r.and_then(|(key, full_url, thumb_url, blurhash)| { let full_trimmed = trim_url(&*full_server, &full_url); @@ -181,10 +102,31 @@ fn main() { Err(AviaryError::ServerError(format!("Received bad response from server: {}", full_url))) } })) + .map_ok(|(key, full_url, thumb_url, blurhash)| protobuf::image::Image { + key: key.into(), + full_url, thumb_url, blurhash, + special_fields: Default::default() + }) .collect::, _>>() + .and_then(|image_info|{ + let index = protobuf::index::Index { + images: image_info, + title: args.title, + desc: None, + special_fields: Default::default() + }; + let index_key = crypto::make_key(); + let encrypted_index = crypto::encrypt( + &index_key, + &index.write_to_bytes() + .expect("Error serializing protocol buffers") + ); + let encoded_key = base64::encode(index_key); + upload::put_data(&agent, &*full_server, &encrypted_index) + .map_err(|e| AviaryError::from_upload_error(e)) + .map(|url| format!("{}#{}", url.trim(), &encoded_key)) + }) .unwrap(); - upload_records.into_iter() - .for_each(|(key, full_url, thumb_url, blurhash)| - println!("{}, {}, {}, {}", base64::encode(key), full_url, thumb_url, blurhash)) + println!("Success! {}", index_url); } } diff --git a/src/protobuf/image.rs b/src/protobuf/image.rs new file mode 100644 index 0000000..426c27d --- /dev/null +++ b/src/protobuf/image.rs @@ -0,0 +1,251 @@ +// This file is generated by rust-protobuf 3.1.0. Do not edit +// .proto file is parsed by protoc --rust-out=... +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_results)] +#![allow(unused_mut)] + +//! Generated file from `image.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_1_0; + +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:Image) +pub struct Image { + // message fields + // @@protoc_insertion_point(field:Image.key) + pub key: ::std::vec::Vec, + // @@protoc_insertion_point(field:Image.full_url) + pub full_url: ::std::string::String, + // @@protoc_insertion_point(field:Image.thumb_url) + pub thumb_url: ::std::string::String, + // @@protoc_insertion_point(field:Image.blurhash) + pub blurhash: ::std::string::String, + // special fields + // @@protoc_insertion_point(special_field:Image.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a Image { + fn default() -> &'a Image { + ::default_instance() + } +} + +impl Image { + pub fn new() -> Image { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(4); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "key", + |m: &Image| { &m.key }, + |m: &mut Image| { &mut m.key }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "full_url", + |m: &Image| { &m.full_url }, + |m: &mut Image| { &mut m.full_url }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "thumb_url", + |m: &Image| { &m.thumb_url }, + |m: &mut Image| { &mut m.thumb_url }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "blurhash", + |m: &Image| { &m.blurhash }, + |m: &mut Image| { &mut m.blurhash }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "Image", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for Image { + const NAME: &'static str = "Image"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.key = is.read_bytes()?; + }, + 18 => { + self.full_url = is.read_string()?; + }, + 26 => { + self.thumb_url = is.read_string()?; + }, + 34 => { + self.blurhash = is.read_string()?; + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.key.is_empty() { + my_size += ::protobuf::rt::bytes_size(1, &self.key); + } + if !self.full_url.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.full_url); + } + if !self.thumb_url.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.thumb_url); + } + if !self.blurhash.is_empty() { + my_size += ::protobuf::rt::string_size(4, &self.blurhash); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.key.is_empty() { + os.write_bytes(1, &self.key)?; + } + if !self.full_url.is_empty() { + os.write_string(2, &self.full_url)?; + } + if !self.thumb_url.is_empty() { + os.write_string(3, &self.thumb_url)?; + } + if !self.blurhash.is_empty() { + os.write_string(4, &self.blurhash)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> Image { + Image::new() + } + + fn clear(&mut self) { + self.key.clear(); + self.full_url.clear(); + self.thumb_url.clear(); + self.blurhash.clear(); + self.special_fields.clear(); + } + + fn default_instance() -> &'static Image { + static instance: Image = Image { + key: ::std::vec::Vec::new(), + full_url: ::std::string::String::new(), + thumb_url: ::std::string::String::new(), + blurhash: ::std::string::String::new(), + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for Image { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("Image").unwrap()).clone() + } +} + +impl ::std::fmt::Display for Image { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for Image { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x0bimage.proto\"m\n\x05Image\x12\x10\n\x03key\x18\x01\x20\x01(\x0cR\ + \x03key\x12\x19\n\x08full_url\x18\x02\x20\x01(\tR\x07fullUrl\x12\x1b\n\t\ + thumb_url\x18\x03\x20\x01(\tR\x08thumbUrl\x12\x1a\n\x08blurhash\x18\x04\ + \x20\x01(\tR\x08blurhashJ\x86\x02\n\x06\x12\x04\0\0\x07\x01\n\x08\n\x01\ + \x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x07\x01\n\n\n\x03\x04\ + \0\x01\x12\x03\x02\x08\r\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x08\x16\n\ + \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x08\r\n\x0c\n\x05\x04\0\x02\0\x01\ + \x12\x03\x03\x0e\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\ + \x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x08\x1c\n\x0c\n\x05\x04\0\x02\x01\ + \x05\x12\x03\x04\x08\x0e\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0f\ + \x17\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x1a\x1b\n\x0b\n\x04\x04\0\ + \x02\x02\x12\x03\x05\x08\x1d\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\ + \x08\x0e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0f\x18\n\x0c\n\x05\ + \x04\0\x02\x02\x03\x12\x03\x05\x1b\x1c\n\x0b\n\x04\x04\0\x02\x03\x12\x03\ + \x06\x08\x1c\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x08\x0e\n\x0c\n\ + \x05\x04\0\x02\x03\x01\x12\x03\x06\x0f\x17\n\x0c\n\x05\x04\0\x02\x03\x03\ + \x12\x03\x06\x1a\x1bb\x06proto3\ +"; + +/// `FileDescriptorProto` object which was a source for this generated file +fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new(); + file_descriptor_proto_lazy.get(|| { + ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() + }) +} + +/// `FileDescriptor` object which allows dynamic access to files +pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { + static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new(); + static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new(); + file_descriptor.get(|| { + let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { + let mut deps = ::std::vec::Vec::with_capacity(0); + let mut messages = ::std::vec::Vec::with_capacity(1); + messages.push(Image::generated_message_descriptor_data()); + let mut enums = ::std::vec::Vec::with_capacity(0); + ::protobuf::reflect::GeneratedFileDescriptor::new_generated( + file_descriptor_proto(), + deps, + messages, + enums, + ) + }); + ::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor) + }) +} diff --git a/src/protobuf/index.rs b/src/protobuf/index.rs new file mode 100644 index 0000000..3327b3d --- /dev/null +++ b/src/protobuf/index.rs @@ -0,0 +1,235 @@ +// This file is generated by rust-protobuf 3.1.0. Do not edit +// .proto file is parsed by protoc --rust-out=... +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_results)] +#![allow(unused_mut)] + +//! Generated file from `index.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_1_0; + +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:Index) +pub struct Index { + // message fields + // @@protoc_insertion_point(field:Index.images) + pub images: ::std::vec::Vec, + // @@protoc_insertion_point(field:Index.title) + pub title: ::std::option::Option<::std::string::String>, + // @@protoc_insertion_point(field:Index.desc) + pub desc: ::std::option::Option<::std::string::String>, + // special fields + // @@protoc_insertion_point(special_field:Index.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a Index { + fn default() -> &'a Index { + ::default_instance() + } +} + +impl Index { + pub fn new() -> Index { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(3); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( + "images", + |m: &Index| { &m.images }, + |m: &mut Index| { &mut m.images }, + )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "title", + |m: &Index| { &m.title }, + |m: &mut Index| { &mut m.title }, + )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "desc", + |m: &Index| { &m.desc }, + |m: &mut Index| { &mut m.desc }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "Index", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for Index { + const NAME: &'static str = "Index"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.images.push(is.read_message()?); + }, + 18 => { + self.title = ::std::option::Option::Some(is.read_string()?); + }, + 26 => { + self.desc = ::std::option::Option::Some(is.read_string()?); + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + for value in &self.images { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; + }; + if let Some(v) = self.title.as_ref() { + my_size += ::protobuf::rt::string_size(2, &v); + } + if let Some(v) = self.desc.as_ref() { + my_size += ::protobuf::rt::string_size(3, &v); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + for v in &self.images { + ::protobuf::rt::write_message_field_with_cached_size(1, v, os)?; + }; + if let Some(v) = self.title.as_ref() { + os.write_string(2, v)?; + } + if let Some(v) = self.desc.as_ref() { + os.write_string(3, v)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> Index { + Index::new() + } + + fn clear(&mut self) { + self.images.clear(); + self.title = ::std::option::Option::None; + self.desc = ::std::option::Option::None; + self.special_fields.clear(); + } + + fn default_instance() -> &'static Index { + static instance: Index = Index { + images: ::std::vec::Vec::new(), + title: ::std::option::Option::None, + desc: ::std::option::Option::None, + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for Index { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("Index").unwrap()).clone() + } +} + +impl ::std::fmt::Display for Index { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for Index { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x0bindex.proto\x1a\x0bimage.proto\"n\n\x05Index\x12\x1e\n\x06images\ + \x18\x01\x20\x03(\x0b2\x06.ImageR\x06images\x12\x19\n\x05title\x18\x02\ + \x20\x01(\tH\0R\x05title\x88\x01\x01\x12\x17\n\x04desc\x18\x03\x20\x01(\ + \tH\x01R\x04desc\x88\x01\x01B\x08\n\x06_titleB\x07\n\x05_descJ\x84\x02\n\ + \x06\x12\x04\0\0\x08\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\ + \x12\x03\x02\0\x15\n\n\n\x02\x04\0\x12\x04\x04\0\x08\x01\n\n\n\x03\x04\0\ + \x01\x12\x03\x04\x08\r\n\x0b\n\x04\x04\0\x02\0\x12\x03\x05\x08\"\n\x0c\n\ + \x05\x04\0\x02\0\x04\x12\x03\x05\x08\x10\n\x0c\n\x05\x04\0\x02\0\x06\x12\ + \x03\x05\x11\x16\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x05\x17\x1d\n\x0c\n\ + \x05\x04\0\x02\0\x03\x12\x03\x05\x20!\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ + \x06\x08\"\n\x0c\n\x05\x04\0\x02\x01\x04\x12\x03\x06\x08\x10\n\x0c\n\x05\ + \x04\0\x02\x01\x05\x12\x03\x06\x11\x17\n\x0c\n\x05\x04\0\x02\x01\x01\x12\ + \x03\x06\x18\x1d\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x06\x20!\n\x0b\n\ + \x04\x04\0\x02\x02\x12\x03\x07\x08!\n\x0c\n\x05\x04\0\x02\x02\x04\x12\ + \x03\x07\x08\x10\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x07\x11\x17\n\x0c\ + \n\x05\x04\0\x02\x02\x01\x12\x03\x07\x18\x1c\n\x0c\n\x05\x04\0\x02\x02\ + \x03\x12\x03\x07\x1f\x20b\x06proto3\ +"; + +/// `FileDescriptorProto` object which was a source for this generated file +fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new(); + file_descriptor_proto_lazy.get(|| { + ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() + }) +} + +/// `FileDescriptor` object which allows dynamic access to files +pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { + static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new(); + static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new(); + file_descriptor.get(|| { + let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { + let mut deps = ::std::vec::Vec::with_capacity(1); + deps.push(super::image::file_descriptor().clone()); + let mut messages = ::std::vec::Vec::with_capacity(1); + messages.push(Index::generated_message_descriptor_data()); + let mut enums = ::std::vec::Vec::with_capacity(0); + ::protobuf::reflect::GeneratedFileDescriptor::new_generated( + file_descriptor_proto(), + deps, + messages, + enums, + ) + }); + ::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor) + }) +} diff --git a/src/protobuf/mod.rs b/src/protobuf/mod.rs new file mode 100644 index 0000000..8b4421b --- /dev/null +++ b/src/protobuf/mod.rs @@ -0,0 +1,4 @@ +// @generated + +pub mod image; +pub mod index;