Crates.io | collections-fromstr |
lib.rs | collections-fromstr |
version | 0.1.1 |
source | src |
created_at | 2021-05-14 18:12:17.415089 |
updated_at | 2021-05-14 18:16:18.497651 |
description | Derives FromStr for collection types like Vec |
homepage | |
repository | https://github.com/snowpoke/collections-fromstr |
max_upload_size | |
id | 397518 |
size | 19,374 |
This crate provides a FromStr
derive for newtypes on iterable collections on single types, such Vec<T>
or HashSet<T>
. The element is parsed by splitting the input along a pattern that you specify though the #[item_separator]
attribute. The individual items are then parsed using their respective FromStr
implementations.
<T>
and assume that it is the inner type. It will assume that T
in this example is the item type.T
must not be an actual type (no trait type) that implements FromStr
.FromIterator<Item = T>
(like Vec<T>
or HashSet<T>
).From
needs to be implemented between your newtype and its inner type. Crates like derive_more
take easy care of that.use collections_fromstr::FromStr;
use derive_more::From;
use std::str::FromStr;
#[derive(From, FromStr, PartialEq)]
#[item_separator = ","]
struct NewVec(Vec<i32>);
static VALUES: &str = "1,2,3,-3,-2,-1";
assert!(
NewVec::from_str(VALUES).unwrap() == NewVec(vec![1,2,3,-3,-2,-1])
);
Iterator::split
for this, right?Okay, hear me out. Say you've got data like this:
1-3:B,I,U//43-60:I//83-87:I,U//99-104: B,I// [etc.]
Let's say this data represents text markup: You've got character ranges on the left of the colon :
, and highlighting information on the right side (B
= bold, I
= italics, U
= underline, but you'll probably expand it later once you get that hedgefund money), of which there might be multiple, separated by commas ,
. Each markup is separated by double slashes //
.
... Now look at the magic of FromStr
doing its thing:
use std::collections::HashSet;
use derive_more::From;
use std::ops::Range;
#[derive(parse_display::FromStr)]
#[display("{0.start}-{0.end}")]
struct CharRange(#[from_str(default)] Range<u32>);
#[derive(parse_display::FromStr, Hash, PartialEq, Eq)]
#[non_exhaustive]
enum MarkupOperation {
#[display("B")]
Bold,
#[display("I")]
Italics,
#[display("U")]
Underline,
}
#[derive(From, collections_fromstr::FromStr)]
#[item_separator=","]
struct Operations(HashSet<MarkupOperation>);
#[derive(parse_display::FromStr)]
#[display("{range}:{operations}")]
struct Markup{
range: CharRange,
operations: Operations,
}
#[derive(From, collections_fromstr::FromStr)]
#[item_separator="//"]
struct MarkupVec(Vec<Markup>);
Look at this code. It's. So. Clean. 🥺 You'll also be less likely to produce bugs, like forgetting about the case of an empty input string.
collections-fromstr
is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE
and LICENSE-MIT
for details.