1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#![allow(dead_code)]
use std::result;

#[derive(Debug)]
enum ParseError {
    MissingDelimiter,
    MalformedString,
}

type ParseResult<T> = result::Result<T, ParseError>;

pub struct QueryPair {
    param: String,
    value: String
}

pub fn parse_query(query: &str) -> Option<Vec<QueryPair>> {
    let mut parsed: Vec<QueryPair> = Vec::new();
    for part in query.split('&') {
        match get_pair(&part) {
            Ok(pair) => parsed.push(pair),
            Err(_) => break
        }
    }
    match parsed.len() {
        0 => None,
        _ => Some(parsed)
    }
}

fn get_pair(raw: &str) -> ParseResult<QueryPair> {
    let pieces: Vec<_> = raw.split('=').collect();
    if pieces.len() < 2 {
        Err(ParseError::MissingDelimiter)
    } else if pieces.len() > 2 {
        Err(ParseError::MalformedString)
    } else {
        Ok(QueryPair{param: String::from(pieces[0]), value: String::from(pieces[1])})
    }
}

#[test]
fn test_single_param() {
    let single_param: &'static str = "test=true";
    let parsed = parse_query(&single_param);
    match parsed {
        Some(p) => assert!(p.len() == 1),
        None => panic!("failed to parse 'test=true'")
    }
}

#[test]
fn test_multiple_param() {
    let multi_param: &'static str = "test1=true&test2=false";
    let parsed = parse_query(&multi_param);
    match parsed {
        Some(p) => assert!(p.len() == 2),
        None => panic!("failed to parse 'test1=true,test2=false'")
    }
}