Saturday 4 September 2021

rust sample code: splitting array of string on comma and space

 

I'm keeping this code snippet because it isn't going to make it into dust and I think it's impressive.


/**
* Takes an Option<iterable of string> and returns a HashSet of strings that have been
* split by comma and whitespace
*/
fn clean_input<'a, I>(cmd_line_arg: Option<I>) -> HashSet<&'a str>
where
I: Iterator<Item = &'a str>,
{
match cmd_line_arg {
Some(aa) => aa
.map(|a| {
a.split_whitespace()
.map(|bb| bb.split(','))
.flatten()
.collect::<Vec<&str>>()
})
.flatten()
.filter(|a| !a.is_empty())
.collect::<HashSet<&str>>(),
None => HashSet::new(),
}
}


Monday 11 May 2020

Tests & Assertions

This makes life easier by highlighting failing string matches in color at the appropriate place:

https://docs.rs/pretty_assertions/0.1.0/pretty_assertions/

Tuesday 4 February 2020

Borrowing Self / Dealing with passing &mut self

https://users.rust-lang.org/t/is-rc-a-good-way-to-work-around-partial-borrow-of-self/37442/6


Thursday 12 December 2019

Building

Hide warnings on build:

* RUSTFLAGS=-Awarnings  cargo build            

Dependency Tree:

* cargo tree

Build cargo with all features:

  • cargo build --all-features   
          
Specifying it in Cargo.toml:
  • my_lib = { git = "ssh://git@github.com/a/b.git", features = ["test_utils"], branch = "master" }
  •  
Use of versions in dependencies:

```
[dependencies]
time = "0.1.12"
```
The string "0.1.12" is a semver version requirement. Since this string does not have any operators in it, it is interpreted the same way as if we had specified "^0.1.12", which is called a caret requirement. This will download 0.1.MAX not 0.1.12. If you need to specify the exact version use "=0.1.12"


Cargo lock in .gitignore:

* If you’re building a library that other projects will depend on, put Cargo.lock in your .gitignore. 
* If you’re building an executable like a command-line tool or an application, check Cargo.lock into git.


Friday 1 November 2019

Package collision




The below conflict means you are using a different version of the library to one of your dependencies:


expected enum `THING`, found a different enum `THING`
  
    = note: expected type `&THING` (enum `THING`)
               found type `&THING` (enum `THING`)
note: Perhaps two different versions of crate `NAME` are being used?


This can be checked with (may need to cargo install cargo-tree)

cargo tree


A quick and dirty fix is for Packages to be overriden in cargo.toml with something like:
patch.crates.io if you are really are patching crates.io otherwise specify the url you are patching

[patch.crates-io]
r2d2 = { git = "https://github.com/PassFort/r2d2", branch = "handle-panics-0.8.6" }
[dependencies]
...
to_patch = { git = "ssh://git@github.com/company/project.git"}

[patch.'ssh://github.com/company/project.git']
to_patch= { git = "ssh://git@github.com/company/project.git", }

/\ Note you can't use to_patch and specify a branch. Fork the repo in github or point to a local build.


Or use replace (requires lib name AND version (assumed to be 0.1.0 here):

[replace]
"to_patch:0.1.0" = { git = "ssh://git@github.com/company/project.git" branch="fix"}

Alternatively if you need 2 version of a crate:



It is apparently possible to import 2 different crate versions
 
Cargo.toml: 
[dependencies]
md5 = "0.6"
other-md5 = { version = "0.8", package = "md-5" }
  
code:
use md5::compute;
use other_md5::Md5;

Sunday 13 October 2019

Traits in structs.


I am currently aware of 2 ways to handle the fact you can't put a trait in a struct. (Reason: Traits don't have size at compile time)

1) Box the trait
2) Use an enum instead of a trait (enums have a size at compile time).

If you box the trait, you may end up needing to clone it. Cloning a boxed object is possible here is how to do it:

Cut and Paste of the relevant code here:

trait Foo {
    fn box_clone(&self) -> Box<Foo>;
}

impl Clone for Box<Foo>
{
    fn clone(&self) -> Box<Foo> {
        self.box_clone()
    }
}

#[derive(Clone)]
struct Bar;

impl Foo for Bar {
    fn box_clone(&self) -> Box<Foo> {
        Box::new((*self).clone())
    }
}

#[test]
fn it_works() {
    let baz = Box::new(Bar) as Box<Foo>;
    let qux = baz.clone();
}

If using Box across Threads (eg Rayon) you must implement Send & Sync
https://gist.github.com/bootandy/468230baaec80d04fb3a9a9e885e3d5a