|
14 | 14 | | [Handle invalid CSV data with Serde][ex-invalid-csv] | [![csv-badge]][csv] [![serde-badge]][serde] | [![cat-encoding-badge]][cat-encoding] |
|
15 | 15 | | [Serialize records to CSV][ex-serialize-csv] | [![csv-badge]][csv] | [![cat-encoding-badge]][cat-encoding] |
|
16 | 16 | | [Serialize records to CSV using Serde][ex-csv-serde] | [![csv-badge]][csv] [![serde-badge]][serde] | [![cat-encoding-badge]][cat-encoding] |
|
| 17 | +| [Transform one column of a CSV file][ex-csv-transform-column] | [![csv-badge]][csv] [![serde-badge]][serde] | [![cat-encoding-badge]][cat-encoding] | |
17 | 18 | | [Get MIME type from string][ex-mime-from-string] | [![mime-badge]][mime] | [![cat-encoding-badge]][cat-encoding] |
|
18 | 19 |
|
19 | 20 | [ex-json-value]: #ex-json-value
|
@@ -688,6 +689,107 @@ fn run() -> Result<()> {
|
688 | 689 | #
|
689 | 690 | # quick_main!(run);
|
690 | 691 | ```
|
| 692 | +[ex-csv-transform-column]: #ex-csv-transform-column |
| 693 | +<a name="ex-csv-transform-column"></a> |
| 694 | +## Transform CSV column |
| 695 | + |
| 696 | +[![csv-badge]][csv] [![serde-badge]][serde] [![cat-encoding-badge]][cat-encoding] |
| 697 | + |
| 698 | +Transform a CSV file containing a color name and a hex color into one with a |
| 699 | +color name and an rgb color. Utilizes the [csv] crate to read and write the |
| 700 | +csv file, and [serde] to deserialize and serialize the rows to and from bytes. |
| 701 | + |
| 702 | +See [`csv::Reader::deserialize`], [`serde::Deserialize`], and [`std::str::FromStr`] |
| 703 | + |
| 704 | +```rust |
| 705 | +extern crate csv; |
| 706 | +# #[macro_use] |
| 707 | +# extern crate error_chain; |
| 708 | +#[macro_use] |
| 709 | +extern crate serde_derive; |
| 710 | +extern crate serde; |
| 711 | + |
| 712 | +use csv::{Reader, Writer}; |
| 713 | +use serde::{de, Deserialize, Deserializer}; |
| 714 | +use std::str::FromStr; |
| 715 | +# |
| 716 | +# error_chain! { |
| 717 | +# foreign_links { |
| 718 | +# CsvError(csv::Error); |
| 719 | +# ParseInt(std::num::ParseIntError); |
| 720 | +# CsvInnerError(csv::IntoInnerError<Writer<Vec<u8>>>); |
| 721 | +# IO(std::fmt::Error); |
| 722 | +# UTF8(std::string::FromUtf8Error); |
| 723 | +# } |
| 724 | +# } |
| 725 | + |
| 726 | +#[derive(Debug)] |
| 727 | +struct HexColor { |
| 728 | + red: u8, |
| 729 | + green: u8, |
| 730 | + blue: u8, |
| 731 | +} |
| 732 | + |
| 733 | +#[derive(Debug, Deserialize)] |
| 734 | +struct Row { |
| 735 | + color_name: String, |
| 736 | + color: HexColor, |
| 737 | +} |
| 738 | + |
| 739 | +impl FromStr for HexColor { |
| 740 | + type Err = Error; |
| 741 | + |
| 742 | + fn from_str(hex_color: &str) -> std::result::Result<Self, Self::Err> { |
| 743 | + let trimmed = hex_color.trim_matches('#'); |
| 744 | + if trimmed.len() != 6 { |
| 745 | + Err("Invalid length of hex string".into()) |
| 746 | + } else { |
| 747 | + Ok(HexColor { |
| 748 | + red: u8::from_str_radix(&trimmed[..2], 16)?, |
| 749 | + green: u8::from_str_radix(&trimmed[2..4], 16)?, |
| 750 | + blue: u8::from_str_radix(&trimmed[4..6], 16)?, |
| 751 | + }) |
| 752 | + } |
| 753 | + } |
| 754 | +} |
| 755 | + |
| 756 | +impl<'de> Deserialize<'de> for HexColor { |
| 757 | + fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> |
| 758 | + where |
| 759 | + D: Deserializer<'de>, |
| 760 | + { |
| 761 | + let s = String::deserialize(deserializer)?; |
| 762 | + FromStr::from_str(&s).map_err(de::Error::custom) |
| 763 | + } |
| 764 | +} |
| 765 | + |
| 766 | +fn run() -> Result<()> { |
| 767 | + let data = "color_name,color |
| 768 | +red,#ff0000 |
| 769 | +green,#00ff00 |
| 770 | +blue,#0000FF |
| 771 | +periwinkle,#ccccff |
| 772 | +magenta,#ff00ff" |
| 773 | + .to_owned(); |
| 774 | + let mut out = Writer::from_writer(vec![]); |
| 775 | + let mut reader = Reader::from_reader(data.as_bytes()); |
| 776 | + for result in reader.deserialize::<Row>() { |
| 777 | + let res = result?; |
| 778 | + out.serialize(( |
| 779 | + res.color_name, |
| 780 | + res.color.red, |
| 781 | + res.color.green, |
| 782 | + res.color.blue, |
| 783 | + ))?; |
| 784 | + } |
| 785 | + let written = String::from_utf8(out.into_inner()?)?; |
| 786 | + assert_eq!(Some("magenta,255,0,255"), written.lines().last()); |
| 787 | + println!("{}", written); |
| 788 | + Ok(()) |
| 789 | +} |
| 790 | +# |
| 791 | +# quick_main!(run); |
| 792 | +``` |
691 | 793 |
|
692 | 794 | [ex-mime-from-string]: #ex-mime-from-string
|
693 | 795 | <a name="ex-mime-from-string"></a>
|
@@ -729,17 +831,20 @@ fn main() {
|
729 | 831 | <!-- API Reference -->
|
730 | 832 |
|
731 | 833 | [`csv::ByteRecord`]: https://docs.rs/csv/*/csv/struct.ByteRecord.html
|
732 |
| -[`csv::invalid_option`]: https://docs.rs/csv/*/csv/fn.invalid_option.html |
733 | 834 | [`csv::Reader::deserialize`]: https://docs.rs/csv/*/csv/struct.Reader.html#method.deserialize
|
| 835 | +[`csv::Reader::deserialize`]: https://docs.rs/csv/\*/csv/struct.Reader.html#method.deserialize |
734 | 836 | [`csv::StringRecord`]: https://docs.rs/csv/*/csv/struct.StringRecord.html
|
735 | 837 | [`csv::Writer`]: https://docs.rs/csv/*/csv/struct.Writer.html
|
| 838 | +[`csv::invalid_option`]: https://docs.rs/csv/*/csv/fn.invalid_option.html |
736 | 839 | [`flush`]: https://docs.rs/csv/*/csv/struct.Writer.html#method.flush
|
737 | 840 | [`form_urlencoded::byte_serialize`]: https://docs.rs/url/*/url/form_urlencoded/fn.byte_serialize.html
|
738 | 841 | [`form_urlencoded::parse`]: https://docs.rs/url/*/url/form_urlencoded/fn.parse.html
|
739 | 842 | [`FromStrError`]: https://docs.rs/mime/*/mime/struct.FromStrError.html
|
740 | 843 | [`MIME`]: https://docs.rs/mime/*/mime/struct.Mime.html
|
741 | 844 | [`percent_decode`]: https://docs.rs/url/*/url/percent_encoding/fn.percent_decode.html
|
| 845 | +[`serde::Deserialize`]: https://docs.rs/serde/\*/serde/trait.Deserialize.html |
742 | 846 | [`serialize`]: https://docs.rs/csv/*/csv/struct.Writer.html#method.serialize
|
| 847 | +[`std::str::FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
743 | 848 | [`utf8_percent_encode`]: https://docs.rs/url/*/url/percent_encoding/fn.utf8_percent_encode.html
|
744 | 849 | [`write_record`]: https://docs.rs/csv/*/csv/struct.Writer.html#method.write_record
|
745 | 850 |
|
|
0 commit comments