toml 0.6.0

  • Readme
  • Changelog
  • Installing
  • 52

toml.dart #

This package provides an implementation of a TOML (Tom's Obvious, Minimal Language) parser and encoder for Dart.

It currently supports version v0.4.0 of the TOML specification.

Installation #

To get started add toml as a dependency to your pubspec.yaml and run the pub get command.

dependencies:
  toml: "^0.6.0"

Usage #

This package includes three libraries for loading, decoding and encoding TOML documents, which are further described below.

If you want to use both the encoder and decoder, a single import suffices.

import 'package:toml/toml.dart';

Load configuration files. #

Before any configuration file can be parsed the library needs to know how to load it. There are two default methods available, but you can easily implement your own loading mechanism as further described below.

If your code is running in the browser, you probably want to use XHR to fetch the file from the server. To do so import the toml.loader.http library and call the static HttpConfigLoader.use method, e.g., from your main function.

import 'package:toml/loader/http.dart';

void main() {
  HttpConfigLoader.use();
  // ...
}

If your code is running on the server, you can load configuration files from the local file system. Simply import the toml.loader.fs library and call the static FilesystemConfigLoader.use method, e.g., from your main function.

import 'package:toml/loader/fs.dart';

void main() {
  FilesystemConfigLoader.use();
  // ...
}

For convenience both libraries export the loadConfig function from the toml.loader library. It optionally takes the path to the configuration file as its only argument (defaults to 'config.toml') and returns a Future of the parsed configuration options.

Future main() async {
  // ...
  var cfg = await loadConfig();
  // ...
}

Implement a custom loader. #

To create a custom loader which fits exactly your needs import the toml.loader library, create a new class and implement the ConfigLoader interface. You can use the following template as a starting point.

library my.config.loader;

import 'package:toml/loader.dart';
export 'package:toml/loader.dart' show loadConfig;

class MyConfigLoader implements ConfigLoader {

  static void use() {
    ConfigLoader.use(new MyConfigLoader());
  }

  @override
  Future<String> loadConfig(String filename) {
    // ...
  }

}

In your main function invoke the MyConfigLoader.use method and call the loadConfig function as usual.

Decode TOML #

If you only want to decode a string of TOML, add the following import directive to your script.

import 'package:toml/decoder.dart';

This library contains the actual TomlParser class whose parse method takes a String and returns a Result object. The results value property holds an unmodifiable Map of the parsed document.

var toml = '''
  # ...
''';
var parser = new TomlParser();
var document = parser.parse(toml).value;

Encode TOML #

This package includes a TOML encoder. To use it add the following import.

import 'package:toml/encoder.dart';

The library provides a TomlEncoder class whose encode method takes a Map and returns a TOML encoded String. All values of the map must be natively representable by TOML or implement the TomlEncodable interface.

var document = {
  // ...
};
var encoder = new TomlEncoder();
var toml = encoder.encode(document);

Classes which implement the TomlEncodable interface define a toToml method whose return value can be represented by TOML in turn.

Data Structure #

TOML documents and tables as well as inline tables are represented through nested UnmodifiableMapView objects whose keys are Strings and values dynamic read-only representations of the corresponding TOML value or sub-table. The contents of a table declared by

[a.b.c]
key = 'value'

may be accessed using [] as shown in the listing below.

var table = document['a']['b']['c']; // ok
var value = table['key'];

The following, however, is invalid.

var table = document['a.b.c']; // error
table['key'] = value; // error

All kinds of arrays including arrays of tables are stored as UnmodifiableListView objects. Though the encoder accepts any Iterable. The items of the list represent either a value or a table. Consider the document that contains an array of tables.

[[items]]
name = 'A'

[[items]]
name = 'B'

[[items]]
name = 'C'

It is possible to iterate over the tables in the array.

document['items'].forEach((Map item) { // ok
  print(item.name);
});

However, it is not allowed to add, remove or modify its entries.

document['items'].add({ // error
  'name': 'D'
});
document['items'][0] = { // error
  'name': 'E'
};

All string variants produce regular dart Strings. All of the following are therefore equivalent.

str1 = "Hello World!"
str2 = 'Hello World!'
str3 = """
  Hello \
  World!\
"""
str4 = '''Hello World!'''

Integers are of type int and floating point numbers are represented as doubles. When compiled to JavaScript these two types are not distinct. Thus a float without decimal places might accidentally be encoded as an integer. This behavior would lead to the generation of invalid numeric arrays. The TomlEncoder addresses this issue by analyzing the contents of numeric arrays first. If any of its items cannot be represented as an integer, all items will be encoded as floats instead. Encoding the following map, for example, would throw an MixedArrayTypesException in the VM.

var document = {
  'array': [1, 2.0, 3.141]
};

However, in JavaScript, the encoder yields the following TOML document.

array = [1.0, 2.0, 3.141]

Boolean values are obviously of type bool.

Datetime values are UTC DateTime objects.

Examples #

Check out the scripts located in the ./example directory.

Testing #

To see whether everything is working correctly change into the root directory of this package and run the included tests as follows:

pub run test

You may pass the --platform command line argument to test the package on other platforms than the VM. Run pub run test --help for a list of all available platforms.

Alternatively, you can run [toml-test][] (again from the package root):

$GOPATH/bin/toml-test bin/decoder.dart
$GOPATH/bin/toml-test -encoder bin/encoder.dart

Unfortunately, some tests from toml-test are failing at the moment. Thus, toml.dart is not fully v0.4.0 compliant at the moment. We will fix the failing tests in an upcoming release of this library soon.

License #

toml.dart is licensed under the MIT license agreement. See the LICENSE file for details.

Changelog #

0.6.0 / 2020-05-22 #

  • Upgraded to Dart 2.

0.5.1 / 2017-06-19 #

  • Upgraded dependencies.

0.5.0 / 2016-07-24 #

  • Removed deprecated use*ConfigLoader functions.
  • Improved testing and added support for BurntSushi's toml-test suite.

0.4.0 / 2015-06-05 #

  • Removed deprecated toml.browser and toml.server libraries.
  • Dropped support for dart_config. There is now a custom ConfigLoader interface with two default implementations.
  • The use*ConfigLoader functions are still available for backward compatibility, but are deprecated and will be removed in the next release. Each of the ConfigLoader implementations has a static use method which you should use instead.

0.3.0 / 2015-04-08 #

  • Introduced new toml.loader library.
  • The toml.browser and toml.server libraries are now deprecated and will be removed in the next release. Use the new toml.loader library instead.

0.2.0 / 2015-02-12 #

  • Updated to v0.4.0 of the TOML spec.
  • Added bare/quoted keys.
  • Added inline table syntax.
  • Allowed underscores in numbers.
  • Removed forward slash as an escapable character.

0.1.1 / 2015-01-26 #

  • Fixed links and markdown.

0.1.0 / 2015-01-23 #

  • Initial version, implements v0.3.1 of the TOML spec.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  toml: ^0.6.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:toml/toml.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
32
Health:
Code health derived from static analysis. [more]
75
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
70
Overall:
Weighted score of the above. [more]
52
Learn more about scoring.

We analyzed this package on Jul 9, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14

Health suggestions

Fix lib/src/decoder/parser.dart. (-8.17 points)

Analysis of lib/src/decoder/parser.dart reported 17 hints, including:

line 23 col 46: Use = to separate a named parameter from its default value.

line 23 col 69: Use = to separate a named parameter from its default value.

line 27 col 62: Use = to separate a named parameter from its default value.

line 43 col 11: Unnecessary new keyword.

line 49 col 18: Unnecessary new keyword.

Fix lib/src/encoder/builder.dart. (-7.71 points)

Analysis of lib/src/encoder/builder.dart reported 16 hints, including:

line 47 col 39: Unnecessary new keyword.

line 50 col 29: Unnecessary new keyword.

line 68 col 51: Use = to separate a named parameter from its default value.

line 87 col 36: DO use curly braces for all flow control structures.

line 102 col 37: Use = to separate a named parameter from its default value.

Fix lib/src/decoder/grammar.dart. (-2.48 points)

Analysis of lib/src/decoder/grammar.dart reported 5 hints:

line 16 col 46: Unnecessary new keyword.

line 37 col 38: Use = to separate a named parameter from its default value.

line 89 col 46: Use = to separate a named parameter from its default value.

line 89 col 69: Use = to separate a named parameter from its default value.

line 102 col 62: Use = to separate a named parameter from its default value.

Fix additional 12 files with analysis or formatting issues. (-10.47 points)

Additional issues in the following files:

  • lib/src/decoder/interface.dart (5 hints)
  • bin/encoder.dart (3 hints)
  • bin/decoder.dart (2 hints)
  • lib/decoder/yaml.dart (2 hints)
  • lib/loader/fs.dart (2 hints)
  • lib/decoder/json.dart (1 hint)
  • lib/decoder/toml.dart (1 hint)
  • lib/loader/http.dart (1 hint)
  • lib/loader/stream.dart (1 hint)
  • lib/src/decoder/value.dart (1 hint)
  • lib/src/encoder/encoder.dart (1 hint)
  • lib/src/loader/interface.dart (1 hint)

Maintenance issues and suggestions

Make sure dartdoc successfully runs on your package's source files. (-10 points)

Running dartdoc failed with the following output: NoSuchMethodError: The getter 'attributes' was called on null. Receiver: null Tried calling: attributes

#0      DartdocCustomizer._addPubPackageLink (package:pub_dev/dartdoc/customization.dart:168:17)
#1      DartdocCustomizer.customizeHtml (package:pub_dev/dartdoc/customization.dart:61:7)
#2      DartdocCustomizer.customizeFile (package:pub_dev/dartdoc/customization.dart:35:31)
<asynchronous suspension>
#3      DartdocCustomizer.customizeDir (package:pub_dev/dartdoc/customization.dart:26:25)
<asynchronous suspension>
#4      DartdocJobProcessor.process (package:pub_dev/dartdoc/dartdoc_runner.dart:211:14)
<asynchronous suspension>
#5      JobProcessor.run (package:pub_dev/job/job.dart:65:28)
<asynchronous suspension>
#6      JobMaintenance.run (package:pub_dev/job/job.dart:106:18)
#7      _workerMain.<anonymous closure> (package:pub_dev/service/entrypoint/dartdoc.dart:108:26)
#8      StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#9      StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#10     StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#11     _rootRunUnary (dart:async/zone.dart:1192:38)
#12     _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#13     _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
#14     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
#15     Future._propagateToListeners (dart:async/future_impl.dart:711:32)
#16     Future._completeWithValue (dart:async/future_impl.dart:526:5)
#17     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
#18     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
#19     DartdocJobProcessor.generateDocsForSdk (package:pub_dev/dartdoc/dartdoc_runner.dart)
#20     StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#21     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#22     StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#23     _rootRunUnary (dart:async/zone.dart:1192:38)
#24     _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#25     _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
#26     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
#27     Future._propagateToListeners (dart:async/future_impl.dart:711:32)
#28     Future._completeWithValue (dart:async/future_impl.dart:526:5)
#29     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
#30     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
#31     VersionedJsonStorage.hasCurrentData (package:pub_dev/shared/storage.dart)
#32     StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#33     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#34     StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#35     _rootRunUnary (dart:async/zone.dart:1192:38)
#36     _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#37     _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
#38     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
#39     Future._propagateToListeners (dart:async/future_impl.dart:711:32)
#40     Future._completeWithValue (dart:async/future_impl.dart:526:5)
#41     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
#42     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
#43     ApiRequester.request (package:_discoveryapis_commons/src/clients.dart)
#44     StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#45     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#46     StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#47     _rootRunUnary (dart:async/zone.dart:1192:38)
#48     _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#49     _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
#50     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
#51     Future._propagateToListeners (dart:async/future_impl.dart:711:32)
#52     Future._complete (dart:async/future_impl.dart:516:7)
#53     Stream.join.<anonymous closure> (dart:async/stream.dart:847:18)
#54     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#55     StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#56     _rootRun (dart:async/zone.dart:1180:38)
#57     _CustomZone.run (dart:async/zone.dart:1077:19)
#58     _CustomZone.runGuarded (dart:async/zone.dart:979:7)
#59     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:392:13)
#60     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:402:15)
#61     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:286:7)
#62     _SinkTransformerStreamSubscription._close (dart:async/stream_transformers.dart:98:11)
#63     _EventSinkWrapper.close (dart:async/stream_transformers.dart:25:11)
#64     _StringAdapterSink.close (dart:convert/string_conversion.dart:251:11)
#65     _Utf8ConversionSink.close (dart:convert/string_conversion.dart:302:20)
#66     _ConverterStreamEventSink.close (dart:convert/chunked_conversion.dart:83:18)
#67     _SinkTransformerStreamSubscription._handleDone (dart:async/stream_transformers.dart:143:24)
#68     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#69     StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#70     _rootRun (dart:async/zone.dart:1180:38)
#71     _CustomZone.run (dart:async/zone.dart:1077:19)
#72     _CustomZone.runGuarded (dart:async/zone.dart:979:7)
#73     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:392:13)
#74     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:402:15)
#75     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:286:7)
#76     _ForwardingStream._handleDone (dart:async/stream_pipe.dart:108:10)
#77     _ForwardingStreamSubscription._handleDone (dart:async/stream_pipe.dart:174:13)
#78     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#79     StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#80     _rootRun (dart:async/zone.dart:1180:38)
#81     _CustomZone.run (dart:async/zone.dart:1077:19)
#82     _CustomZone.runGuarded (dart:async/zone.dart:979:7)
#83     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:392:13)
#84     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:402:15)
#85     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:286:7)
#86     _ForwardingStream._handleDone (dart:async/stream_pipe.dart:108:10)
#87     _ForwardingStreamSubscription._handleDone (dart:async/stream_pipe.dart:174:13)
#88     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#89     StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#90     _rootRun (dart:async/zone.dart:1180:38)
#91     _CustomZone.run (dart:async/zone.dart:1077:19)
#92     _CustomZone.runGuarded (dart:async/zone.dart:979:7)
#93     _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:392:13)
#94     _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:402:15)
#95     _BufferingStreamSubscription._close (dart:async/stream_impl.dart:286:7)
#96     _SyncStreamControllerDispatch._sendDone (dart:async/stream_controller.dart:787:19)
#97     _StreamController._closeUnchecked (dart:async/stream_controller.dart:644:7)
#98     _StreamController.close (dart:async/stream_controller.dart:637:5)
#99     _HttpParser._closeIncoming (dart:_http/http_parser.dart:1121:23)
#100    _HttpParser._doParse (dart:_http/http_parser.dart:815:15)
#101    _HttpParser._parse (dart:_http/http_parser.dart:328:7)
#102    _HttpParser._onData (dart:_http/http_parser.dart:850:5)
#103    StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#104    StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#105    StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#106    _rootRunUnary (dart:async/zone.dart:1192:38)
#107    _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#108    _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
#109    _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
#110    _BufferingStreamSubscription._add (dart:async/stream_impl.dart:266:7)
#111    _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:779:19)
#112    _StreamController._add (dart:async/stream_controller.dart:655:7)
#113    _StreamController.add (dart:async/stream_controller.dart:597:5)
#114    _Socket._onData (dart:io-patch/socket_patch.dart:1982:41)
#115    StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:26)
#116    StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#117    StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:129:14)
#118    _rootRunUnary (dart:async/zone.dart:1192:38)
#119    _CustomZone.runUnary (dart:async/zone.dart:1085:19)
#120    _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
#121    _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
#122    _BufferingStreamSubscription._add (dart:async/stream_impl.dart:266:7)
#123    _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:779:19)
#124    _StreamController._add (dart:async/stream_controller.dart:655:7)
#125    _StreamController.add (dart:async/stream_controller.dart:597:5)
#126    _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:1018:19)
#127    StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#128    StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#129    _rootRun (dart:async/zone.dart:1180:38)
#130    _CustomZone.run (dart:async/zone.dart:1077:19)
#131    _CustomZone.runGuarded (dart:async/zone.dart:979:7)
#132    _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1019:23)
#133    StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
#134    StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
#135    _rootRun (dart:async/zone.dart:1184:13)
#136    _CustomZone.run (dart:async/zone.dart:1077:19)
#137    _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1003:23)
#138    Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
#139    _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
#140    _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
#141    _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (petitparser).

Homepage URL isn't helpful. (-10 points)

Update the homepage field from pubspec.yaml: link to a website about the package or use the source repository URL.

Maintain an example.

None of the files in the package's example/ directory matches known example patterns.

Common filename patterns include main.dart, example.dart, and toml.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
path ^1.6.4 1.7.0
petitparser ^2.4.0 2.4.0 3.0.4
quiver ^2.1.3 2.1.3
yaml ^2.2.1 2.2.1
Transitive dependencies
charcode 1.1.3
collection 1.14.13 1.15.0-nnbd
matcher 0.12.8
meta 1.2.1
source_span 1.7.0
stack_trace 1.9.5
string_scanner 1.0.5
term_glyph 1.1.0
Dev dependencies
build_runner any
build_test any
build_web_compilers any
test any