Repository navigation
Releases: jjant/ini-edit
Releases · jjant/ini-edit
Release list
v0.5.0
Changed
- Breaking: a new editing API that can no longer corrupt a document. Every operation that can fail returns
Result<_, EditError>, and a refused edit changes nothing.Editor::new(source, &parse_options, &edit_options)?replacesnew,with_parse_options,with_edit_optionsandwith_options.Editor::section(name)is a lookup that returnsOptionand never creates a section;section_or_insert(name)?creates one, andpreamble()edits the keys before the first header (0.4'ssection("")appended a[]section instead). Positions count body lines, so the header is never one:insert_entry,append_body_lines,insert_body_lines,remove_body_linesandbody_line_countreplaceinsert_entry_at_line,append_raw_lines,insert_raw_lines_at,remove_linesand the header-at-0 indexing, and out-of-range positions and reversed ranges are errors instead of being clamped. Handles borrow the editor exclusively, so a stale or removed handle no longer compiles;entry(key)andentry_at(index)replaceentries_mut(), andEntryEditor::index()and the newbody_line()are always current.remove_entryandrename_keyreturnResult<bool, EditError>, and a rename onto an existing key isErr(DuplicateKey).SeparatorSpacing::exact(before, after)?validates its whitespace, and theExactfields are the newWhitespacetype. Theeditormodule docs have a migration guide whose examples are compiled (#90) - Breaking: move to rowan 0.17.
SyntaxNode,SyntaxToken,SyntaxElement,Parse::green()andIniLang'srowan::Languageimpl now use rowan 0.17's types, so code that names rowan types needsrowan = "0.17". rowan 0.17 removes its mutable tree API (clone_for_update,detach,SyntaxNode::splice_children,new_root_mut, the*_by_kindhelpers), andSyntaxNode::green()returns&GreenNodeDatainstead of aCow: replacegreen().into_owned()withgreen().to_owned(), and edit throughEditoror by rebuilding green nodes withreplace_with(#99) - Diagnostics describe the INI text instead of internal token names, and each position gets at most one diagnostic.
=badreportsexpected a key before '='(wasunexpected token: LEX_ERROR),:xreportsexpected a key before ':',key junkreports onlyexpected '=' or ':'(orunexpected text after keywhenallow_no_valueis on), and a lone[reportsexpected section name and ']'instead of two diagnostics. Code that matches onParseError::messageor counts diagnostics will see the new text (#101)
Added
EditorisSend + Sync + UnwindSafe + RefUnwindSafe, andSectionEditorandEntryEditorareSend + Sync. The crate docs' new "Threads" section lists which types can cross threads; syntax nodes, tokens and theasttypes still cannot (#99, #102)ini_edit::MAX_INPUT_LEN, the largest document a tree can describe (u32::MAXbytes). The editor refuses documents and edits past its limit withEditError::DocumentTooLarge(#90, #93)
Fixed
- The editor no longer writes text that a reader would read back differently. Keys, values, section names, separator spacing and raw lines that would not round-trip are refused instead of written: for example, setting a value to
"a\n[evil]\nx=1"used to move every following entry into a new[evil]section, a key likea=bread back as the keya, and padded section names created a duplicate section every time the file was reopened. Values ending in a backslash, which absorbed the next line, are refused too (#90) - The editor's view always equals a reparse of its text. Raw lines containing line breaks, lines inserted above a header and removing a header used to leave the editor's tree disagreeing with the saved file, so later edits went to different lines depending on whether the file was reopened in between. Raw lines are now parsed, so a raw
k=2is an entry thatsetandrename_keyfind (#90) ParseError::displayputs the caret under the reported column. It was two columns to the left, three from line 1000 on, and further with tabs (#101)parseandparse_withpanic with a clear message on input longer thanMAX_INPUT_LENinstead of returning a tree whose length wrapped around (a 4 GiB document gave an empty tree with no diagnostics in release builds) (#93)- The published crate's own tests pass: 0.4.0's package left out the snapshot files, so 31 tests failed on its crates.io sources (#84)
Performance
Measured against 0.4.0 from crates.io on the same machine; parsing speed is unchanged.
- Editing is faster:
Editor::finishis about three times faster (gitea'sapp.example.ini: 364 to 115 µs), 200setcalls in one section of a 10,000-entry file are 29% faster and 200append_entrycalls 55% faster, because each edit rebuilds one immutable section instead of splicing a mutable tree line by line (#99) - The typed AST reads keys, values, names and comments directly from the tree's green nodes: walking every entry of an already-parsed
app.example.initakes 7 µs instead of 22, and finding one key 0.8 µs instead of 2.4 (#100)
Documentation
- Add SECURITY.md (private vulnerability reporting), CONTRIBUTING.md, and docs/standards.md, which records how ini-edit applies TigerStyle and SQLite's testing practices and the deliberate deviations (#86)
v0.4.0
Changed
- Breaking: every malformed line is now a single node in the syntax tree. A line that starts with an unexpected token is wrapped in the new
SyntaxKind::ERROR_LINE, and text after a key without a separator (key junk) stays inside itsENTRY. Code that matches exhaustively onSyntaxKind, or walks the children of malformed lines, needs updating. Diagnostics are unchanged (#60) - Lines added by the editor use the document's line ending instead of always
\n. This is the first line break in the current text, or\nif there is none, so editing CRLF or CR files no longer mixes line endings (#63) - Report unexpected text after a section header (
[s] extra) as a parse error. It was previously accepted silently (#52) - With both
allow_no_valueandinline_commentsenabled, a bare key can carry an inline comment (quick # note). This was previously a parse error, and assigning a value glued the comment onto it (#62) Editor::file()returns an immutable snapshot, as documented, instead of the editor's live tree, so a saved view no longer changes when the editor is edited (#54)
Fixed
- Editing a key followed by junk (
key junk, MySQL's!includedir /path) no longer glues the new value onto the junk, and removing that key no longer leaves the junk behind as a new key (#60) remove_linesandinsert_raw_lines_atcount each malformed line as one line, so later indices are no longer shifted and removing a line can no longer join two lines (#60)- Keep a bare
\rand a following\nas two line breaks when inserting lines, including between lines inserted together, so line indices match a reopened file (#61) - Keep a bare
\rand a following\nas two line breaks when deleting entries, sections, or lines in files with mixed line endings (#58) insert_entry_at_linewith alinepast the last content line inserts exactly whereappend_entrydoes, including after trailing malformed lines (#66)- Don't count a leading UTF-8 BOM as a column in
ParseError::line_colanddisplay(#59) - Parse a first line that is indented after a UTF-8 BOM, and keep the BOM when removing the first section or entry (#45)
- Fix a panic when adding to a retained section handle after removing all its lines, and keep insertions from joining lines after deletions (#47)
- Give the same results whether or not a file is saved and reopened between edits. Inserted line breaks belong to their line, so
remove_linescan no longer join a header to a setting, and a new section after an empty, unterminated value no longer ends up inside that value (#49) - Clearing a value no longer turns its inline comment into the value when the file is reopened (#50)
- Assigning a continued value that ends on a blank line no longer absorbs the inline comment, and clearing a value with
CompactorExactspacing no longer keeps the old surrounding spaces (#53)
Performance
- Parse input with many malformed lines in linear time instead of quadratic time (#46)
- Repair line boundaries between inserted lines before attaching them to the document, about twice as fast for large raw-line batches that need repairs (#64)
Documentation
- Explain that a value ending in a backslash continues on the next line when the file is reopened (#67)
v0.3.2
v0.3.1
Fixed
- Add a canonical separator when assigning a value to a bare key, preventing invalid output such as
flagon(#39) - Preserve bare-CR line endings during verbatim raw-line insertion (#39)
- Report accurate parse-error locations and source excerpts for LF, CRLF, and bare-CR input (#39)
- Make empty and reversed
remove_linesranges safe no-ops instead of panicking (#39)
Changed
v0.3.0
v0.2.1
Added
- Snapshot tests for error diagnostics (#29)
- Line/column display for
ParseError(#28) - Benchmark comparison against
rust-ini(#27) allow_no_valueparse option for bare keys (#26)- Real-world INI fixture tests (#25)
- Editor fuzz target and edge case tests (#24)
Fixed
- Out-of-bounds panic in editor surfaced by fuzzing (#24)