#attributes #macro-derive #struct #accessor #boilerplate #fields #self

macro viewit

Attribute and derive macros for creating accessors for struct

6 releases

0.1.5 Apr 16, 2023
0.1.4 Apr 1, 2023
0.1.2 Mar 5, 2023
0.0.1 Mar 5, 2023

#829 in Procedural macros

Download history 18/week @ 2023-12-19 31/week @ 2023-12-26 1/week @ 2024-01-09 169/week @ 2024-02-06 307/week @ 2024-02-13 142/week @ 2024-02-20 2139/week @ 2024-02-27 380/week @ 2024-03-05 24/week @ 2024-03-12 1294/week @ 2024-03-19

3,863 downloads per month
Used in 11 crates (10 directly)

Apache-2.0/MIT

38KB
795 lines

ViewIt

ViewIt contains a derive macro and a attribute macro to help you avoid writing boilerplate code. See introduction for more details.

github Build

docs.rs crates.io crates.io

license-apache license-mit

Introduction

By default, fields of a struct in Rust are private, but add visibility for the fields one by one is annoying, so the viewit attribute macro will help you do such things.

Without viewit:

pub struct Foo {
  pub f1: u8,
  pub f2: u16,
  pub f3: String,
  pub f4: Vec<u8>
}

With viewit:

use viewit::viewit;

#[viewit]
pub struct Foo {
  f1: u8,
  f2: u16,
  f3: String,
  f4: Vec<u8>
}

By default, viewit will use the struct's visibility for each field, and the expand code is equal to the below.

pub struct Foo {
    pub f1: u8,
    pub f2: u16,
    pub f3: String,
    pub f4: Vec<u8>,
}
impl Foo {
    #[inline]
    pub fn f1(&self) -> &u8 {
        &self.f1
    }
    #[inline]
    pub fn f2(&self) -> &u16 {
        &self.f2
    }
    #[inline]
    pub fn f3(&self) -> &String {
        &self.f3
    }
    #[inline]
    pub fn f4(&self) -> &Vec<u8> {
        &self.f4
    }
    #[inline]
    pub fn set_f1(mut self, val: u8) -> Self {
        self.f1 = val;
        self
    }
    #[inline]
    pub fn set_f2(mut self, val: u16) -> Self {
        self.f2 = val;
        self
    }
    #[inline]
    pub fn set_f3(mut self, val: String) -> Self {
        self.f3 = val;
        self
    }
    #[inline]
    pub fn set_f4(mut self, val: Vec<u8>) -> Self {
        self.f4 = val;
        self
    }
}

Advance Usages

viewit have mutliple useful configs to help you generate what you want flexibly.


use viewit::viewit;

struct FromString {
  src: String,
}

impl From<&String> for FromString {
  fn from(src: &String) -> Self {
    Self { src: src.clone() }
  }
}


fn vec_to_string(src: &[u8]) -> String {
  String::from_utf8_lossy(src).to_string()
}

#[viewit(
  // set this, then this visibility will be applied to the fields
  vis_all = "pub(crate)",
  // this will not generate setters
  setters(
    // change the prefix for all setters
    prefix = "with",
    // change the setters fn style, available values here are ref, into, tryinto or move
    style = "ref",
    // if you do not want to generate getters, you can use skip
    // skip, 
  ),
  getters(
    // change the prefix for all getters
    prefix = "get",
    // change the getters fn style, available values here are ref and move
    style = "ref",
    // if you do not want to generate getters, you can use skip
    // skip,
  ),
  // print the generated code to std out, other available values here are: stderr or "path/to/output/file"
  debug = "stdout"
)]
struct Foo {
  #[viewit(
    getter(
      style = "move",
      rename = "get_first_field",
      vis = "pub" // we can custom field getter
    ),
    setter(
      skip, // we do not want the setter for the field, then we skip it.
    )
  )]
  f1: u8,
  #[viewit(
    getter(
      skip, // we do not want the getter for the field, then we skip it
    )
  )]
  f2: u16,

  #[viewit(
    getter(
      result(
        // sometimes we may want to convert the f4 field to a generic type
        type = "T",
        converter(
          style = "ref", // take the ownership of the field
          fn = "T::from", // the fn used to do the conversion
        ),
        // set the trait bound
        bound = "T: for<'a> From<&'a String>"
      )
    )
  )]
  f3: String,

  #[viewit(
    getter(
      result(
        // we want to convert the f3 field to String
        type = "String",
        converter(
          style = "ref", // take the reference of the field
          fn = "vec_to_string" // the fn used to do the conversion
        ),
      )
    )
  )]
  f4: Vec<u8>,
}

viewit will help you to generate the code:

struct Foo {
    pub(crate) f1: u8,
    pub(crate) f2: u16,
    pub(crate) f3: String,
    pub(crate) f4: Vec<u8>,
}
impl Foo {
    #[inline]
    pub fn get_first_field(&self) -> u8 {
        self.f1
    }
    #[inline]
    pub(crate) fn get_f3<T: for<'a> From<&'a String>>(&self) -> T {
        T::from(&self.f3)
    }
    #[inline]
    pub(crate) fn get_f4(&self) -> String {
        vec_to_string(&self.f4)
    }
    #[inline]
    pub(crate) fn with_f2(&mut self, val: u16) {
        self.f2 = val;
    }
    #[inline]
    pub(crate) fn with_f3(&mut self, val: String) {
        self.f3 = val;
    }
    #[inline]
    pub(crate) fn with_f4(&mut self, val: Vec<u8>) {
        self.f4 = val;
    }
}

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~2MB
~47K SLoC