Last active
February 4, 2023 01:24
-
-
Save heaths/b2cb43db72a9de5e0b5c28127f4d263a to your computer and use it in GitHub Desktop.
Deserialize an autorest readme.md file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use clap::Parser; | |
use markdown::{tokenize, Block, Span}; | |
use serde::Deserialize; | |
use std::fs::File; | |
use std::io::Read; | |
use std::path::PathBuf; | |
fn main() { | |
let args = Args::parse(); | |
let mut f = File::open(args.file).expect("failed to open autorest config"); | |
let mut content = String::new(); | |
f.read_to_string(&mut content) | |
.expect("failed to read autorest config"); | |
let mut tags: Vec<String> = vec![]; | |
let tag = match args.tag { | |
Some(ref s) => Some(s.as_str()), | |
None => None, | |
}; | |
for block in tokenize(&content) { | |
match block { | |
Block::Header(spans, 3) if spans.len() == 1 => { | |
if let Span::Text(header) = &spans[0] { | |
if header.starts_with("Tag:") { | |
let header = header | |
.strip_prefix("Tag:") | |
.and_then(|s| Some(s.trim())) | |
.unwrap_or_default(); | |
tags.push(header.to_string()); | |
} | |
} | |
} | |
Block::CodeBlock(Some(s), content) | |
if tag.is_some() && s.contains("yaml") && s.contains(tag.unwrap()) => | |
{ | |
let config: Config = serde_yaml::from_str(content.as_str()) | |
.expect("failed to parse autorest config"); | |
if let Some(files) = config.input_files { | |
for file in files.to_vec() { | |
println!("{}", file); | |
} | |
} | |
return; | |
} | |
_ => { | |
if args.debug { | |
eprintln!("{:?}", block); | |
} | |
} | |
} | |
} | |
match args.tag { | |
Some(tag) => { | |
eprintln!("{} not defined", tag); | |
std::process::exit(2); | |
} | |
None => { | |
tags.sort(); | |
tags.reverse(); | |
for tag in tags { | |
println!("{}", tag); | |
} | |
} | |
} | |
} | |
#[derive(Parser)] | |
#[command(version, about, long_about = None)] | |
struct Args { | |
/// The autorest.md file to parse. | |
file: PathBuf, | |
/// The tag to parse. | |
#[arg(short, long)] | |
tag: Option<String>, | |
/// Print debugging information. | |
#[arg(long)] | |
debug: bool, | |
} | |
#[derive(Deserialize)] | |
struct Config { | |
// Deserialize either a string (rare) or array of strings. | |
#[serde(rename = "input-file")] | |
input_files: Option<StringOrStringArray>, | |
} | |
#[derive(Deserialize)] | |
#[serde(untagged)] | |
enum StringOrStringArray { | |
Str(String), | |
StrArray(Vec<String>), | |
} | |
impl StringOrStringArray { | |
fn to_vec(self) -> Vec<String> { | |
match self { | |
Self::StrArray(arr) => arr, | |
Self::Str(s) => vec![s], | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment