use crate::Warning;
pub struct Output<T> {
output: T,
warnings: Vec<Warning>,
}
impl<T> Output<T> {
pub fn new(value: T) -> Self {
Output { output: value, warnings: Vec::new() }
}
pub fn with_warnings(mut self, warnings: Vec<Warning>) -> Self {
self.warnings = warnings;
self
}
pub fn get_output(&self) -> &T {
&self.output
}
pub fn mut_output(&mut self) -> &mut T {
&mut self.output
}
pub fn has_warnings(&self) -> bool {
!self.warnings.is_empty()
}
pub fn get_warnings(&self) -> &Vec<Warning> {
&self.warnings
}
pub fn take(self) -> (T, Vec<Warning>) {
(self.output, self.warnings)
}
}
impl<T,E> Output<Result<T,E>> {
pub fn is_ok(&self) -> bool {
self.output.is_ok()
}
pub fn is_err(&self) -> bool {
self.output.is_err()
}
pub fn into_ok<U, F>(self) -> Output<Result<U,F>> where T: Into<U> {
let (res, warnings) = self.take();
let ok:U = res.ok().unwrap().into();
Output::new(Ok(ok)).with_warnings(warnings)
}
pub fn into_err<U, F>(self) -> Output<Result<U,F>> where E: Into<F> {
let (res,warnings) = self.take();
let err:F = res.err().unwrap().into();
Output::new(Err(err)).with_warnings(warnings)
}
pub fn into_result<U,F>(self) -> Output<Result<U,F>> where T: Into<U>, E: Into<F> {
if self.is_ok() {
self.into_ok()
} else {
self.into_err()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let out:Output<u8> = Output::new(5);
assert!(!out.has_warnings());
assert_eq!(out.get_output(), &5);
assert_eq!(out.get_warnings(), &Vec::new());
let (x,w) = out.take();
assert_eq!(x, 5);
assert_eq!(w, Vec::new());
}
#[test]
fn basic_with_warnings() {
use crate::WarningKind;
use crate::FullContext;
let context = FullContext::from(None, "".to_string());
let warnings = vec![ Warning::new(WarningKind::DuplicateStoryData, Some(context.clone())),
Warning::new(WarningKind::DuplicateStoryTitle, Some(context.clone())) ];
let expected = vec![ Warning::new(WarningKind::DuplicateStoryData, Some(context.clone())),
Warning::new(WarningKind::DuplicateStoryTitle, Some(context.clone())) ];
let out:Output<u8> = Output::new(5).with_warnings(warnings);
assert!(out.has_warnings());
assert_eq!(out.get_output(), &5);
assert_eq!(out.get_warnings(), &expected);
let (x,w) = out.take();
assert_eq!(x, 5);
assert_eq!(w, expected);
}
#[test]
fn output_result() {
let ok_out:Output<Result<u8,String>> = Output::new(Ok(5));
let err_out:Output<Result<String,u8>> = Output::new(Err(23));
assert!(ok_out.is_ok());
assert_eq!(ok_out.get_output(), &Ok(5));
assert!(err_out.is_err());
assert_eq!(err_out.get_output(), &Err(23));
let x:Output<Result<u32,u32>> = ok_out.into_ok();
assert!(x.is_ok());
assert_eq!(x.get_output(), &Ok(5));
let y:Output<Result<u64, u64>> = x.into_result();
assert!(y.is_ok());
assert_eq!(y.get_output(), &Ok(5));
let x:Output<Result<u32,u32>> = err_out.into_err();
assert!(x.is_err());
assert_eq!(x.get_output(), &Err(23));
let y:Output<Result<u64, u64>> = x.into_result();
assert!(y.is_err());
assert_eq!(y.get_output(), &Err(23));
}
#[test]
#[should_panic]
fn into_ok_panic() {
let x:Output<Result<u8,u8>> = Output::new(Err(5));
let _:Output<Result<u32,String>> = x.into_ok();
}
#[test]
#[should_panic]
fn into_err_panic() {
let x:Output<Result<u8,u8>> = Output::new(Ok(5));
let _:Output<Result<String,u32>> = x.into_err();
}
}