diff --git a/crates/bitwarden/src/platform/sync.rs b/crates/bitwarden/src/platform/sync.rs index c7aded18a..eec365e48 100644 --- a/crates/bitwarden/src/platform/sync.rs +++ b/crates/bitwarden/src/platform/sync.rs @@ -93,16 +93,14 @@ impl SyncResponse { profile: ProfileResponse::process_response(profile, enc)?, folders: response .folders - .ok_or(Error::MissingFields)? - .into_iter() - .map(|f| f.into()) - .collect(), + .map(|f| f.into_iter().map(|f| f.try_into()).collect()) + .transpose()? + .ok_or(Error::MissingFields)?, collections: response .collections - .ok_or(Error::MissingFields)? - .into_iter() - .map(|c| c.into()) - .collect(), + .map(|c| c.into_iter().map(|c| c.try_into()).collect()) + .transpose()? + .ok_or(Error::MissingFields)?, ciphers: ciphers .into_iter() .map(|c| c.try_into()) @@ -110,16 +108,14 @@ impl SyncResponse { domains: response.domains.map(|d| (*d).try_into()).transpose()?, policies: response .policies - .ok_or(Error::MissingFields)? - .into_iter() - .map(|p| p.try_into()) - .collect::>>()?, + .map(|p| p.into_iter().map(|p| p.try_into()).collect()) + .transpose()? + .ok_or(Error::MissingFields)?, sends: response .sends - .ok_or(Error::MissingFields)? - .into_iter() - .map(|s| s.into()) - .collect(), + .map(|s| s.into_iter().map(|s| s.try_into()).collect()) + .transpose()? + .ok_or(Error::MissingFields)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index ab43df11d..4fc32fce4 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -7,7 +5,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -55,26 +53,27 @@ impl Decryptable for Attachment { url: self.url.clone(), size: self.size.clone(), size_name: self.size_name.clone(), - file_name: self.file_name.decrypt(enc, org_id).unwrap(), + file_name: self.file_name.decrypt(enc, org_id)?, key: self .key .as_ref() - .map(|key| enc.decrypt_bytes(key, org_id).unwrap()), + .map(|key| enc.decrypt_bytes(key, org_id)) + .transpose()?, }) } } -impl From for Attachment { - fn from(attachment: bitwarden_api_api::models::AttachmentResponseModel) -> Self { - Self { +impl TryFrom for Attachment { + type Error = Error; + + fn try_from(attachment: bitwarden_api_api::models::AttachmentResponseModel) -> Result { + Ok(Self { id: attachment.id, url: attachment.url, size: attachment.size.map(|s| s.to_string()), size_name: attachment.size_name, - file_name: attachment - .file_name - .map(|s| EncString::from_str(&s).unwrap()), - key: attachment.key.map(|s| EncString::from_str(&s).unwrap()), - } + file_name: EncString::try_from(attachment.file_name)?, + key: EncString::try_from(attachment.key)?, + }) } } diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 371585560..ece601e1a 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::CipherCardModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +6,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -61,17 +59,17 @@ impl Decryptable for Card { } } -impl From for Card { - fn from(card: CipherCardModel) -> Self { - Self { - cardholder_name: card - .cardholder_name - .map(|s| EncString::from_str(&s).unwrap()), - exp_month: card.exp_month.map(|s| EncString::from_str(&s).unwrap()), - exp_year: card.exp_year.map(|s| EncString::from_str(&s).unwrap()), - code: card.code.map(|s| EncString::from_str(&s).unwrap()), - brand: card.brand.map(|s| EncString::from_str(&s).unwrap()), - number: card.number.map(|s| EncString::from_str(&s).unwrap()), - } +impl TryFrom for Card { + type Error = Error; + + fn try_from(card: CipherCardModel) -> Result { + Ok(Self { + cardholder_name: EncString::try_from(card.cardholder_name)?, + exp_month: EncString::try_from(card.exp_month)?, + exp_year: EncString::try_from(card.exp_year)?, + code: EncString::try_from(card.code)?, + brand: EncString::try_from(card.brand)?, + number: EncString::try_from(card.number)?, + }) } } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 5a569b1f7..deae6bf2b 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -301,9 +301,9 @@ impl TryFrom for Cipher { notes: EncString::try_from(cipher.notes)?, r#type: cipher.r#type.ok_or(Error::MissingFields)?.into(), login: cipher.login.map(|l| (*l).try_into()).transpose()?, - identity: cipher.identity.map(|i| (*i).into()), - card: cipher.card.map(|c| (*c).into()), - secure_note: cipher.secure_note.map(|s| (*s).into()), + identity: cipher.identity.map(|i| (*i).try_into()).transpose()?, + card: cipher.card.map(|c| (*c).try_into()).transpose()?, + secure_note: cipher.secure_note.map(|s| (*s).try_into()).transpose()?, favorite: cipher.favorite.unwrap_or(false), reprompt: cipher .reprompt @@ -313,20 +313,18 @@ impl TryFrom for Cipher { edit: cipher.edit.unwrap_or(true), view_password: cipher.view_password.unwrap_or(true), local_data: None, // Not sent from server - attachments: Some( - cipher - .attachments - .unwrap_or_default() - .into_iter() - .map(|a| a.into()) - .collect(), - ), + attachments: cipher + .attachments + .map(|a| a.into_iter().map(|a| a.try_into()).collect()) + .transpose()?, fields: cipher .fields - .map(|f| f.into_iter().map(|f| f.into()).collect()), + .map(|f| f.into_iter().map(|f| f.try_into()).collect()) + .transpose()?, password_history: cipher .password_history - .map(|p| p.into_iter().map(|p| p.into()).collect()), + .map(|p| p.into_iter().map(|p| p.try_into()).collect()) + .transpose()?, creation_date: cipher.creation_date.ok_or(Error::MissingFields)?.parse()?, deleted_date: cipher.deleted_date.map(|d| d.parse()).transpose()?, revision_date: cipher.revision_date.ok_or(Error::MissingFields)?.parse()?, diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index a78aeef7f..80dd603f0 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::CipherFieldModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -10,7 +8,7 @@ use super::linked_id::LinkedIdType; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] @@ -67,14 +65,19 @@ impl Decryptable for Field { } } -impl From for Field { - fn from(model: CipherFieldModel) -> Self { - Self { - name: model.name.map(|s| EncString::from_str(&s).unwrap()), - value: model.value.map(|s| EncString::from_str(&s).unwrap()), - r#type: model.r#type.map(|t| t.into()).unwrap(), - linked_id: model.linked_id.map(|id| (id as u32).into()), - } +impl TryFrom for Field { + type Error = Error; + + fn try_from(model: CipherFieldModel) -> Result { + Ok(Self { + name: EncString::try_from(model.name)?, + value: EncString::try_from(model.value)?, + r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + linked_id: model + .linked_id + .map(|id| (id as u32).try_into()) + .transpose()?, + }) } } diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index 41305c953..a34298b57 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::CipherIdentityModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +6,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -109,37 +107,29 @@ impl Decryptable for Identity { } } -impl From for Identity { - fn from(identity: CipherIdentityModel) -> Self { - Self { - title: identity.title.map(|s| EncString::from_str(&s).unwrap()), - first_name: identity - .first_name - .map(|s| EncString::from_str(&s).unwrap()), - middle_name: identity - .middle_name - .map(|s| EncString::from_str(&s).unwrap()), - last_name: identity.last_name.map(|s| EncString::from_str(&s).unwrap()), - address1: identity.address1.map(|s| EncString::from_str(&s).unwrap()), - address2: identity.address2.map(|s| EncString::from_str(&s).unwrap()), - address3: identity.address3.map(|s| EncString::from_str(&s).unwrap()), - city: identity.city.map(|s| EncString::from_str(&s).unwrap()), - state: identity.state.map(|s| EncString::from_str(&s).unwrap()), - postal_code: identity - .postal_code - .map(|s| EncString::from_str(&s).unwrap()), - country: identity.country.map(|s| EncString::from_str(&s).unwrap()), - company: identity.company.map(|s| EncString::from_str(&s).unwrap()), - email: identity.email.map(|s| EncString::from_str(&s).unwrap()), - phone: identity.phone.map(|s| EncString::from_str(&s).unwrap()), - ssn: identity.ssn.map(|s| EncString::from_str(&s).unwrap()), - username: identity.username.map(|s| EncString::from_str(&s).unwrap()), - passport_number: identity - .passport_number - .map(|s| EncString::from_str(&s).unwrap()), - license_number: identity - .license_number - .map(|s| EncString::from_str(&s).unwrap()), - } +impl TryFrom for Identity { + type Error = Error; + + fn try_from(identity: CipherIdentityModel) -> Result { + Ok(Self { + title: EncString::try_from(identity.title)?, + first_name: EncString::try_from(identity.first_name)?, + middle_name: EncString::try_from(identity.middle_name)?, + last_name: EncString::try_from(identity.last_name)?, + address1: EncString::try_from(identity.address1)?, + address2: EncString::try_from(identity.address2)?, + address3: EncString::try_from(identity.address3)?, + city: EncString::try_from(identity.city)?, + state: EncString::try_from(identity.state)?, + postal_code: EncString::try_from(identity.postal_code)?, + country: EncString::try_from(identity.country)?, + company: EncString::try_from(identity.company)?, + email: EncString::try_from(identity.email)?, + phone: EncString::try_from(identity.phone)?, + ssn: EncString::try_from(identity.ssn)?, + username: EncString::try_from(identity.username)?, + passport_number: EncString::try_from(identity.passport_number)?, + license_number: EncString::try_from(identity.license_number)?, + }) } } diff --git a/crates/bitwarden/src/vault/cipher/linked_id.rs b/crates/bitwarden/src/vault/cipher/linked_id.rs index 3997f095a..6fb676dfe 100644 --- a/crates/bitwarden/src/vault/cipher/linked_id.rs +++ b/crates/bitwarden/src/vault/cipher/linked_id.rs @@ -10,6 +10,7 @@ pub enum LinkedIdType { Identity(IdentityLinkedIdType), } +use crate::error::{Error, Result}; #[cfg(feature = "mobile")] use crate::UniffiCustomTypeConverter; #[cfg(feature = "mobile")] @@ -73,37 +74,39 @@ pub enum IdentityLinkedIdType { FullName = 418, } -impl From for LinkedIdType { - fn from(value: u32) -> Self { +impl TryFrom for LinkedIdType { + type Error = Error; + + fn try_from(value: u32) -> Result { match value { - 100 => LinkedIdType::Login(LoginLinkedIdType::Username), - 101 => LinkedIdType::Login(LoginLinkedIdType::Password), - 300 => LinkedIdType::Card(CardLinkedIdType::CardholderName), - 301 => LinkedIdType::Card(CardLinkedIdType::ExpMonth), - 302 => LinkedIdType::Card(CardLinkedIdType::ExpYear), - 303 => LinkedIdType::Card(CardLinkedIdType::Code), - 304 => LinkedIdType::Card(CardLinkedIdType::Brand), - 305 => LinkedIdType::Card(CardLinkedIdType::Number), - 400 => LinkedIdType::Identity(IdentityLinkedIdType::Title), - 401 => LinkedIdType::Identity(IdentityLinkedIdType::MiddleName), - 402 => LinkedIdType::Identity(IdentityLinkedIdType::Address1), - 403 => LinkedIdType::Identity(IdentityLinkedIdType::Address2), - 404 => LinkedIdType::Identity(IdentityLinkedIdType::Address3), - 405 => LinkedIdType::Identity(IdentityLinkedIdType::City), - 406 => LinkedIdType::Identity(IdentityLinkedIdType::State), - 407 => LinkedIdType::Identity(IdentityLinkedIdType::PostalCode), - 408 => LinkedIdType::Identity(IdentityLinkedIdType::Country), - 409 => LinkedIdType::Identity(IdentityLinkedIdType::Company), - 410 => LinkedIdType::Identity(IdentityLinkedIdType::Email), - 411 => LinkedIdType::Identity(IdentityLinkedIdType::Phone), - 412 => LinkedIdType::Identity(IdentityLinkedIdType::Ssn), - 413 => LinkedIdType::Identity(IdentityLinkedIdType::Username), - 414 => LinkedIdType::Identity(IdentityLinkedIdType::PassportNumber), - 415 => LinkedIdType::Identity(IdentityLinkedIdType::LicenseNumber), - 416 => LinkedIdType::Identity(IdentityLinkedIdType::FirstName), - 417 => LinkedIdType::Identity(IdentityLinkedIdType::LastName), - 418 => LinkedIdType::Identity(IdentityLinkedIdType::FullName), - _ => panic!("Invalid LinkedIdType value: {}", value), + 100 => Ok(LinkedIdType::Login(LoginLinkedIdType::Username)), + 101 => Ok(LinkedIdType::Login(LoginLinkedIdType::Password)), + 300 => Ok(LinkedIdType::Card(CardLinkedIdType::CardholderName)), + 301 => Ok(LinkedIdType::Card(CardLinkedIdType::ExpMonth)), + 302 => Ok(LinkedIdType::Card(CardLinkedIdType::ExpYear)), + 303 => Ok(LinkedIdType::Card(CardLinkedIdType::Code)), + 304 => Ok(LinkedIdType::Card(CardLinkedIdType::Brand)), + 305 => Ok(LinkedIdType::Card(CardLinkedIdType::Number)), + 400 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Title)), + 401 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::MiddleName)), + 402 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address1)), + 403 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address2)), + 404 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address3)), + 405 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::City)), + 406 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::State)), + 407 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::PostalCode)), + 408 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Country)), + 409 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Company)), + 410 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Email)), + 411 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Phone)), + 412 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Ssn)), + 413 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Username)), + 414 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::PassportNumber)), + 415 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::LicenseNumber)), + 416 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FirstName)), + 417 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::LastName)), + 418 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FullName)), + _ => Err(Error::MissingFields), } } } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 65369ca64..28e4f93a2 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -7,7 +7,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] @@ -47,11 +47,13 @@ impl Decryptable for SecureNote { } } -impl From for SecureNote { - fn from(model: CipherSecureNoteModel) -> Self { - Self { - r#type: model.r#type.map(|t| t.into()).unwrap(), - } +impl TryFrom for SecureNote { + type Error = Error; + + fn try_from(model: CipherSecureNoteModel) -> Result { + Ok(Self { + r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + }) } } diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 6ca1bcac1..4c1d2fdff 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::CollectionDetailsResponseModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +6,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -56,15 +54,17 @@ impl Decryptable for Collection { } } -impl From for Collection { - fn from(collection: CollectionDetailsResponseModel) -> Self { - Collection { - id: collection.id.unwrap(), - organization_id: collection.organization_id.unwrap(), - name: EncString::from_str(&collection.name.unwrap()).unwrap(), +impl TryFrom for Collection { + type Error = Error; + + fn try_from(collection: CollectionDetailsResponseModel) -> Result { + Ok(Collection { + id: collection.id.ok_or(Error::MissingFields)?, + organization_id: collection.organization_id.ok_or(Error::MissingFields)?, + name: collection.name.ok_or(Error::MissingFields)?.parse()?, external_id: collection.external_id, hide_passwords: collection.hide_passwords.unwrap_or(false), read_only: collection.read_only.unwrap_or(false), - } + }) } } diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 77e59eae4..98cfe4599 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::FolderResponseModel; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -9,7 +7,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -50,12 +48,14 @@ impl Decryptable for Folder { } } -impl From for Folder { - fn from(folder: FolderResponseModel) -> Self { - Folder { - id: folder.id.unwrap(), - name: EncString::from_str(&folder.name.unwrap()).unwrap(), - revision_date: folder.revision_date.unwrap().parse().unwrap(), - } +impl TryFrom for Folder { + type Error = Error; + + fn try_from(folder: FolderResponseModel) -> Result { + Ok(Folder { + id: folder.id.ok_or(Error::MissingFields)?, + name: EncString::try_from(folder.name)?.ok_or(Error::MissingFields)?, + revision_date: folder.revision_date.ok_or(Error::MissingFields)?.parse()?, + }) } } diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 8709ae497..810c41873 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::CipherPasswordHistoryModel; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -9,7 +7,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{Decryptable, EncString, Encryptable}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -50,11 +48,13 @@ impl Decryptable for PasswordHistory { } } -impl From for PasswordHistory { - fn from(model: CipherPasswordHistoryModel) -> Self { - Self { - password: EncString::from_str(&model.password).unwrap(), - last_used_date: model.last_used_date.parse().unwrap(), - } +impl TryFrom for PasswordHistory { + type Error = Error; + + fn try_from(model: CipherPasswordHistoryModel) -> Result { + Ok(Self { + password: model.password.parse()?, + last_used_date: model.last_used_date.parse()?, + }) } } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index d865c5762..e03c60bd5 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -10,7 +8,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{derive_shareable_key, Decryptable, EncString, Encryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -280,26 +278,28 @@ impl Encryptable for SendView { } } -impl From for Send { - fn from(send: SendResponseModel) -> Self { - Send { - id: send.id.unwrap(), - access_id: send.access_id.unwrap(), - name: EncString::from_str(&send.name.unwrap()).unwrap(), - notes: send.notes.map(|s| EncString::from_str(&s).unwrap()), - key: EncString::from_str(&send.key.unwrap()).unwrap(), +impl TryFrom for Send { + type Error = Error; + + fn try_from(send: SendResponseModel) -> Result { + Ok(Send { + id: send.id.ok_or(Error::MissingFields)?, + access_id: send.access_id.ok_or(Error::MissingFields)?, + name: send.name.ok_or(Error::MissingFields)?.parse()?, + notes: EncString::try_from(send.notes)?, + key: send.key.ok_or(Error::MissingFields)?.parse()?, password: send.password, - r#type: send.r#type.unwrap().into(), - file: send.file.map(|f| Into::::into(*f)), - text: send.text.map(|t| Into::::into(*t)), + r#type: send.r#type.ok_or(Error::MissingFields)?.into(), + file: send.file.map(|f| (*f).try_into()).transpose()?, + text: send.text.map(|t| (*t).try_into()).transpose()?, max_access_count: send.max_access_count.map(|s| s as u32), - access_count: send.access_count.unwrap() as u32, + access_count: send.access_count.ok_or(Error::MissingFields)? as u32, disabled: send.disabled.unwrap_or(false), hide_email: send.hide_email.unwrap_or(false), - revision_date: send.revision_date.unwrap().parse().unwrap(), - deletion_date: send.deletion_date.unwrap().parse().unwrap(), - expiration_date: send.expiration_date.map(|s| s.parse().unwrap()), - } + revision_date: send.revision_date.ok_or(Error::MissingFields)?.parse()?, + deletion_date: send.deletion_date.ok_or(Error::MissingFields)?.parse()?, + expiration_date: send.expiration_date.map(|s| s.parse()).transpose()?, + }) } } @@ -312,23 +312,27 @@ impl From for SendType { } } -impl From for SendFile { - fn from(file: SendFileModel) -> Self { - SendFile { - id: file.id.unwrap(), - file_name: EncString::from_str(&file.file_name.unwrap()).unwrap(), - size: file.size.unwrap().to_string(), - size_name: file.size_name.unwrap(), - } +impl TryFrom for SendFile { + type Error = Error; + + fn try_from(file: SendFileModel) -> Result { + Ok(SendFile { + id: file.id.ok_or(Error::MissingFields)?, + file_name: file.file_name.ok_or(Error::MissingFields)?.parse()?, + size: file.size.ok_or(Error::MissingFields)?.to_string(), + size_name: file.size_name.ok_or(Error::MissingFields)?, + }) } } -impl From for SendText { - fn from(text: SendTextModel) -> Self { - SendText { - text: text.text.map(|t| EncString::from_str(&t).unwrap()), +impl TryFrom for SendText { + type Error = Error; + + fn try_from(text: SendTextModel) -> Result { + Ok(SendText { + text: EncString::try_from(text.text)?, hidden: text.hidden.unwrap_or(false), - } + }) } }