use std::convert::TryFrom;
use ed25519_dalek::{PublicKey, PUBLIC_KEY_LENGTH};
use serde::{Deserialize, Serialize};
use crate::identity::AuthorError;
use crate::Validate;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(
feature = "db-sqlx",
derive(sqlx::Type, sqlx::FromRow),
sqlx(transparent)
)]
pub struct Author(String);
impl Author {
pub fn new(value: &str) -> Result<Self, AuthorError> {
let author = Self(String::from(value));
author.validate()?;
Ok(author)
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl TryFrom<PublicKey> for Author {
type Error = AuthorError;
fn try_from(public_key: PublicKey) -> Result<Self, Self::Error> {
Self::new(&hex::encode(public_key.to_bytes()))
}
}
impl Validate for Author {
type Error = AuthorError;
fn validate(&self) -> Result<(), Self::Error> {
match hex::decode(self.0.to_owned()) {
Ok(bytes) => {
if bytes.len() != PUBLIC_KEY_LENGTH {
return Err(AuthorError::InvalidLength);
}
}
Err(_) => {
return Err(AuthorError::InvalidHexEncoding);
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::Author;
#[test]
fn validate() {
assert!(Author::new("abcdefg").is_err());
assert!(Author::new("112233445566ff").is_err());
assert!(
Author::new("7cf4f58a2d89e93313f2de99604a814ecea9800cf217b140e9c3a7ba59a5d982").is_ok()
);
}
}