How to indent flow/cadence files in vim correctly - vim

In cadence a resource interface can contain state and methods that needs to be implemented. However when I try to indent a cadence file in vim it will indent the code wrong.
pub resource interface INFT {
pub let id: UInt64
pub fun getName(): String
pub fun getSchemas() : [String]
pub fun resolveSchema(_ schema:String): AnyStruct
}
The result I get after gg=G
pub resource interface INFT {
pub let id: UInt64
pub fun getName(): String
pub fun getSchemas() : [String]
pub fun resolveSchema(_ schema:String): AnyStruct
}
I am not very familiary with indent rules for vim, can anybody help me out? There is a https://github.com/Cian911/vim-cadence project that has some syntax rules but currently it is not complete.

Update: The maintainer has merged a request after we had a discussion that fixes a lot of my issues with this.

Related

is it possible to define a field use the keywords in rust

I am using rust to write a rest api, now the fluter client define the entity like this:
class WordDefinition {
String type;
String name;
List<String> values;
WordDefinition({
this.type,
this.name,
this.values,
});
}
the client use the type as a entity field name, in dart it works fine. But in the server side rust I could not define the field name like this, what should I do to avoid the rust keyword limit when define a entity? is it possible to define a entity name using type like this in rust:
use rocket::serde::Deserialize;
use rocket::serde::Serialize;
#[derive(Deserialize, Serialize)]
#[allow(non_snake_case)]
pub struct WordDefinition {
pub type: String,
pub text: String,
pub translations: Vec<String>,
}
impl Default for WordDefinition {
fn default() -> Self {
WordDefinition {
type: "".to_string(),
text: "".to_string(),
translations: vec![]
}
}
}
I define like this but obviously it could not work as expect in rust.
You can use "raw identifiers" by prefixing a keyword like: r#type.
You might also want to give it a different name in your Rust code, and use #[serde(rename)] to make it serialize with the name "type" like:
struct Foo {
#[serde(rename = "type")]
kind: String
}
Personally, I prefer the second way, because I find r#type a bit annoying to type and ugly, but that's just preference, there's not a "right" way

Factory pattern in Rust

I have a Terminal and a TerminalFactory type. What I want to achieve is a factory pattern or at least an implementation that is similar to it in regards to some key aspects.
In particular, I want every Terminal to have specific properties (e.G. id) that are set by TerminalFactory. In GRASP terms, TerminalFactory is the Creator and the Information Expert because it knows next_id.
TerminalFactory is not a singleton, it is an instance that will be injected in a container that will be handed around where necessary (I'm trying to implement an application based on the composite pattern to achieve the OCP of SOLID).
It looks like everything is in line with the fact that Rust discourages static state unless it's unsafe code.
The problem now is that instances of Terminal have an id which should not be set by arbitrary code. Therefore, it's not pub. On the other hand, it can be gotten. So I added a public getter, like this:
pub struct Terminal {
id: u32, // private
pub name: String
}
impl Terminal {
pub fn get_id(self: &Self) -> u32 {
self.id
}
}
As far as I can tell, there is no friend keyword in rust, no static state I can keep in the Terminal type and TerminalFactory cannot set Terminal::id during creation because it's not public.
I have the impression I can't implement the factory pattern correctly. Maybe I shouldn't even try to transfer "classical patterns" to Rust? Then what about the SOLID principles which are absolutely necessary to manage change in medium-scale applications (say, 50+ types and beyond 10000 lines of code)?
By adding an associate function new(id : u32) to Terminal I completely defeat the purpose of the factory. So this won't make sense, either.
As all of this code will be in a library that is consumed by other Rust code, how can I protect the consumer code from creating broken instances?
Put both types in the same module:
mod terminal {
pub struct Terminal {
id: u32,
pub name: String
}
impl Terminal {
pub fn get_id(&self) -> u32 {
self.id
}
}
pub struct TerminalFactory {
next_id: u32,
}
impl TerminalFactory {
pub fn new() -> Self {
Self {
next_id: 0,
}
}
pub fn new_terminal(&mut self, name: &str) -> Terminal {
let next_id = self.next_id;
self.next_id += 1;
Terminal {
id: next_id,
name: name.to_owned(),
}
}
}
}
Then this is OK:
let mut tf = terminal::TerminalFactory::new();
let t0 = tf.new_terminal("foo");
let t1 = tf.new_terminal("bar");
println!("{} {}", t0.get_id(), t0.name);
println!("{} {}", t1.get_id(), t1.name);
But this is not:
println!("{} {}", t0.id, t0.name); // error: private field
See Visibility and privacy for other scenarios.

Override the default implementation for a single field of a struct using `#[derive(Debug)]`

I have a struct containing general config data for a web application:
#[derive(Debug)]
pub struct AppConfig {
pub db_host: String,
pub timeout: Duration,
pub jwt_signing_key: String,
// more fields
}
jwt_signing_key is a symmetric jwt secret, so much be kept confidential/
This works fine, but I would like to be able to log the contents of an AppConfig for debugging purposes without the JWT secret appearing in logs. Ideally, it would return something along the lines of:
AppConfig {
db_host: "https://blah"
jwt_signing_key: "**********" // key obfuscated
}
One option is to create a thin wrapper:
pub struct AppConfig {
// ...
pub jwt_signing_key: JwtSigningKey,
}
pub struct JwtSigningKey(String);
// custom implementation of Debug
But this would require a large-ish refactor and adds an unnecessary (in my opinion) layer of indirection. (I'm not worried about the performance, but more the code noise)
AppConfig is relatively large and maintaining a manual Debug implementation is extra work I'd rather not have to do every time I want to add a field.
Is there an easier solution?
One option is to create a thin wrapper:
pub struct AppConfig {
// ...
pub jwt_signing_key: JwtSigningKey,
}
pub struct JwtSigningKey(String);
// custom implementation of Debug
I think you should go with this option. The advantage it has is that no matter where in your application the value ends up, it will never be accidentally printed — or used in any other way — without explicitly unwrapping it, whereas replacing Debug of the AppConfig struct will only assist with that one particular case. It's robust against mistakes made while refactoring, too.
The type doesn't have to be so specific as JwtSigningKey; it could be just pub struct Secret<T>(T); and support any kind of secrets you end up working with. There are even libraries to provide such a type (see this thread for comments comparing two of them) which add more features like zeroing the memory when dropped (so that it's less likely that any accidental leak of memory contents might reveal a secret).
See this thread. Essentially, the best way to do it right now is to use the derivative crate, which allows you to do something like this:
use derivative::Derivative;
use std::fmt;
fn obfuscated_formatter(val: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", "*".repeat(val.len()))
}
#[derive(Derivative)]
#[derivative(Debug)]
struct Foo {
normal: String,
#[derivative(Debug(format_with = "obfuscated_formatter"))]
secret: String
}
fn main() {
let foo = Foo {
normal: "asdf".into(),
secret: "foobar".into()
};
println!("{:?}", foo);
}
Playground link

How can I return a gpio_cdev::Error in Rust?

I'm writing a library in Rust using the gpio_cdev crate.
I have a struct, and one of its functions looks like this:
pub fn add_channel(&mut self, name: String, pin: u8) -> Result<(), gpio_cdev::Error> {
let line = self.chip.get_line(pin as u32)?;
...
}
This works fine. Now I want to add validation to the input pin, so that it's not out-of-range. I know this isn't strictly necessary, and that an invalid pin will get caught by chip.get_line(), but this gives a friendlier error message, and can even allow me to place artificial limits on usable pins (ex: if pins above 20 can technically be used, but I know they should never be used by this function).
My code now looks like this:
pub fn add_channel(&mut self, name: String, pin: u8) -> Result<(), gpio_cdev::Error> {
if pin > 20 {
return Err(gpio_cdev::Error::new(format!("Pin {} is out of range!", pin)));
}
let line = self.chip.get_line(pin as u32)?;
...
}
I would think something like that would work, but gpio_cdev::Error doesn't have a new method, or any other way I can figure out to create an instance of it. Is there a way to do this? Or am I doing something fundamentally wrong? Is this struct only meant to be used internally, within the gpio_cdev crate, without any way to create instances from outside the crate?
gpio_cdev::Error implements From<std::io::Error>
so gpio_cdev::Error can be created using std::io::Error using into()
pub fn add_channel(&mut self, name: String, pin: u8) -> Result<(), gpio_cdev::Error> {
if pin > 20 {
let io_err = std::io::Error::new(std::io::ErrorKind::Other, format!("Pin {} is out of range!", pin));
return Err(io_err.into());
}
let line = self.chip.get_line(pin as u32)?;
...
}

How to get struct fields and fields type in a compiler plugin?

I want to generate a HashMap which use struct fields as key, and use usize integer as value.
pub struct Article {
title: String,
content: String,
category: String,
comments: Vec<Comment>
}
pub struct Comment {
content: String
}
My expected output is:
{
title: 0,
content: 1,
category: 2
comments[].content: 3
}
My solution is impl my trait FieldsMapping for both Article and Comment:
pub trait FieldsMapping {
fn get_fields_map(&self) -> HashMap<String, usize>;
}
I want to write a compiler plugin for custom derive FieldsMapping.
How I get all fields within compiler plugin? And how can I know that fields type is Vec or other?
You don't.
Compiler plugins (i.e. procedural macros) are expanded before this information exists, so you can't access it. No, you can't delay expansion until types exist. No, if you turn it into a lint, you can't generate code, which then defeats the purpose of having a procedural macro.

Resources