[Rust] impl TryFrom and try_into()

The TryFrom and try_into() methods are part of the. standard libaray's conversion traits, designed to handle conversions between types in a fallible manner - that is, conversions that might fail.

This is in contrast to `From` and `into()` methods, which are used for infallible conversions, where the conversion is guaranteed to succeed. 

Using `TryFrom` and `try_into()` provides several benefits and use cases over other approaches:

 

use anyhow::{Result, anyhow, Context};
use std::path::PathBuf;
use crate::opts::Opts;

#[derive(Debug)]
pub struct Config {
  pub operation: Operation,
  pub pwd: PathBuf,
  pub config: PathBuf,
}

impl TryFrom<Opts> for Config {
  type Error = anyhow::Error;

  fn try_from(value: Opts) -> Result<Self> {
    // when you impl TryFrom, you can use try_into
    let operation = value.args.try_into()?;
    let config = get_config(value.config)?;
    let pwd = get_pwd(value.pwd)?;

    return Ok(Config {
      operation,
      config,
      pwd,
    });
  }
}

#[derive(Debug)]
pub enum Operation {
  Print(Option<String>),
  Add(String, String),
  Remove(String),
}

impl TryFrom<Vec<String>> for Operation {
  type Error = anyhow::Error;

  fn try_from(value: Vec<String>) -> Result<Self> {
    let mut value = value;
    if value.len() == 0 {
      return Ok(Operation::Print(None));
    }

    let term = value.get(0).expect("expect to exist");
    if term == "add" {
      if value.len() != 3 {
        return Err(anyhow!("opearation add expected 2 arguements but got {}", value.len() - 1));
      }

      let mut drain = value.drain(1..=2);
      return Ok(
        Operation::Add(drain.next().expect("to exist"), drain.next().expect("to exist"))
      )
    }

    if term == "Remove" {
      if value.len() != 2 {
        return Err(anyhow!("opearation remove expected 1 arguements but got {}", value.len() - 1));
      }

      let arg = value.pop().expect("to exist");
      return Ok(
        Operation::Remove(arg)
      );
    }

    if value.len() > 1 {
      return Err(anyhow!("operation pritn expects 0 or 1 arguments, but got {}", value.len()));
    }

    let arg = value.pop().expect("to exist");
    return Ok(Operation::Print(Some(arg)));
  }
}

fn get_config(config: Option<PathBuf>) -> Result<PathBuf> {
  if let Some(v) = config {
    return Ok(v);
  }

  let loc = std::env::var("XDG_CONFIG_HOME").context("unable to get XDG_CONFIG_HOME")?;
  let mut loc = PathBuf::from(loc);

  loc.push("projector");
  loc.push("projector.json");

  return Ok(loc);
}

fn get_pwd(pwd: Option<PathBuf>) -> Result<PathBuf> {
  if let Some(pwd) = pwd {
    return Ok(pwd);
  }

  return Ok(std::env::current_dir().context("errored getting current_dir")?)
}

 

posted @   Zhentiw  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2020-02-26 [TypeScript] as const, force immutability for Object type
2020-02-26 [Typescript] Using 'Pick' to create a sub-type from original type
2019-02-26 [Functional Programming] Capture Side Effects in a Task / Async
2019-02-26 [Compose] 9. Delay Evaluation with LazyBox
2019-02-26 [Functional Programming] Unbox types with foldMap
2018-02-26 [HTML5] Inlining images with SVG and data URIs
2016-02-26 [Unit Testing] Directive testing, require parent controller
点击右上角即可分享
微信分享提示