Skip to content

Commit 8dffd91

Browse files
committed
feat: trailing semicolon is now optional
1 parent ab879c1 commit 8dffd91

File tree

3 files changed

+14
-19
lines changed

3 files changed

+14
-19
lines changed

questdb-confstr/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ service::key1=value1;key2=value2;key3=value3;
1212
```
1313

1414
A few rules:
15-
* The last semicolon is mandatory.
15+
* The last semicolon is optional.
1616
* Service name and keys are case-sensitive.
1717
* Keys are ASCII alphanumeric and can contain underscores.
1818
* Values are case-sensitive unicode strings which can contain any characters,
@@ -21,10 +21,10 @@ A few rules:
2121

2222
## Grammar
2323

24-
```plain
24+
```json
2525
conf_str ::= service "::" params | service
2626
service ::= identifier
27-
params ::= param (";" param)* ";"
27+
params ::= param (";" param)* ";"?
2828
param ::= key "=" value
2929
key ::= identifier
3030
value ::= { value_char }

questdb-confstr/src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ fn parse_ident(
197197
fn parse_value(
198198
iter: &mut Peekable2<CharIndices>,
199199
next_pos: &mut Position,
200-
input_len: usize,
201200
) -> Result<Value, ParsingError> {
202201
let mut value = String::new();
203202
loop {
@@ -220,7 +219,7 @@ fn parse_value(
220219
value.push(c);
221220
let _ = iter.next();
222221
}
223-
(None, _) => return Err(parse_err(ErrorKind::MissingTrailingSemicolon, input_len)),
222+
(None, _) => break,
224223
}
225224
}
226225
Ok(value)
@@ -262,8 +261,8 @@ fn parse_params(
262261
Some((p, c)) => return Err(parse_err(ErrorKind::BadSeparator(('=', c)), p)),
263262
None => return Err(parse_err(ErrorKind::IncompleteKeyValue, input_len)),
264263
}
265-
let value = parse_value(iter, next_pos, input_len)?;
266-
iter.next().unwrap(); // skip ';'
264+
let value = parse_value(iter, next_pos)?;
265+
iter.next(); // skip ';', if present.
267266
params.insert(key, value);
268267
}
269268
Ok(params)

questdb-confstr/tests/tests.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -259,23 +259,19 @@ fn test_incomplete_key_no_value() {
259259
#[test]
260260
fn missing_trailing_semicolon() {
261261
let input = "http::host=localhost;port=9000";
262-
let config = parse_conf_str(input);
263-
assert!(config.is_err());
264-
let err = config.unwrap_err();
265-
assert_eq!(ErrorKind::MissingTrailingSemicolon, err.kind());
266-
assert_eq!(err.position(), 30);
267-
assert_eq!(err.to_string(), "missing trailing semicolon at position 30");
262+
let config = parse_conf_str(input).unwrap();
263+
assert_eq!(config.service(), "http");
264+
assert_eq!(config.get("host"), Some("localhost"));
265+
assert_eq!(config.get("port"), Some("9000"));
268266
}
269267

270268
#[test]
271269
fn escaped_semicolon_missing_trailing() {
272270
let input = "http::host=localhost;port=9000;;";
273-
let config = parse_conf_str(input);
274-
assert!(config.is_err());
275-
let err = config.unwrap_err();
276-
assert_eq!(err.kind(), ErrorKind::MissingTrailingSemicolon);
277-
assert_eq!(err.position(), 32);
278-
assert_eq!(err.to_string(), "missing trailing semicolon at position 32");
271+
let config = parse_conf_str(input).unwrap();
272+
assert_eq!(config.service(), "http");
273+
assert_eq!(config.get("host"), Some("localhost"));
274+
assert_eq!(config.get("port"), Some("9000;"));
279275
}
280276

281277
#[test]

0 commit comments

Comments
 (0)