Skip to content

Commit

Permalink
feat: improve DataSchemaValue handling
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRhb committed Dec 23, 2023
1 parent e6610fe commit 94d6a9b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 25 deletions.
1 change: 1 addition & 0 deletions lib/scripting_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
library scripting_api;

export 'src/scripting_api/consumed_thing.dart';
export 'src/scripting_api/data_schema_value.dart';
export 'src/scripting_api/discovery/discovery_method.dart';
export 'src/scripting_api/discovery/thing_discovery.dart';
export 'src/scripting_api/discovery/thing_filter.dart';
Expand Down
35 changes: 14 additions & 21 deletions lib/src/core/content_serdes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import 'dart:io';
import 'package:http_parser/http_parser.dart';
import 'package:json_schema/json_schema.dart';

import '../../scripting_api.dart' as scripting_api;
import '../definitions/data_schema.dart';
import '../scripting_api/data_schema_value.dart';
import 'codecs/cbor_codec.dart';
import 'codecs/codec_media_type.dart';
import 'codecs/content_codec.dart';
Expand Down Expand Up @@ -175,18 +177,14 @@ class ContentSerdes {
final mimeType = parsedMediaType.mimeType;
final parameters = parsedMediaType.parameters;

List<int> bytes;
final codec = _getCodecFromMediaType(mimeType);

if (codec != null) {
bytes = codec.valueToBytes(value, dataSchema, parameters);
} else {
// Media Type is unsupported. Convert the String representation to bytes
// instead.
// TODO(JKRhb): Could be moved to a dedicated Value class method.
bytes = utf8.encoder.convert(value.toString());
if (codec == null) {
// TODO: Throw UnsupportedError
throw Exception();
}

final bytes = codec.valueToBytes(value, dataSchema, parameters);
return Content(resolvedMediaType, Stream.value(bytes));
}

Expand All @@ -195,7 +193,7 @@ class ContentSerdes {
/// A [dataSchema] can be passed for validating the result. If the media type
/// specified in the [content] is not supported, its body is converted to an
/// UTF-8 string.
Future<Object?> contentToValue(
Future<scripting_api.DataSchemaValue> contentToValue(
Content content,
DataSchema? dataSchema,
) async {
Expand All @@ -204,20 +202,15 @@ class ContentSerdes {
final parameters = parsedMediaType.parameters;

final bytes = await content.toByteList();
final codec = _getCodecFromMediaType(mimeType);

// TODO: Should null be returned in this case?
if (bytes.isEmpty) {
return null;
if (codec == null) {
// TODO: Throw NotSupportedError
throw Exception();
}

final codec = _getCodecFromMediaType(mimeType);
if (codec != null) {
final value = codec.bytesToValue(bytes, dataSchema, parameters);
_validateValue(value, dataSchema);
return value;
} else {
// TODO(JKRhb): Should unsupported data be returned as a String?
return utf8.decode(bytes.toList());
}
final value = codec.bytesToValue(bytes, dataSchema, parameters);
_validateValue(value, dataSchema);
return value;
}
}
23 changes: 21 additions & 2 deletions lib/src/core/interaction_output.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class InteractionOutput implements scripting_api.InteractionOutput {

bool _dataUsed = false;

// TODO: Name these fields
(bool, scripting_api.DataSchemaValue) _value = (false, null);

@override
Future<ByteBuffer> arrayBuffer() async {
_dataUsed = true;
Expand All @@ -44,9 +47,25 @@ class InteractionOutput implements scripting_api.InteractionOutput {
bool get dataUsed => _dataUsed;

@override
Future<Object?> value() async {
Future<scripting_api.DataSchemaValue> value() async {
if (_value.$1) {
return _value.$2;
}

final schema = this.schema;
if (schema == null) {
// TODO: Throw NotReadableError
throw Exception();
}

final value = await _contentSerdes.contentToValue(
_content,
schema,
);
_dataUsed = true;
return _contentSerdes.contentToValue(_content, schema);

_value = (true, value);
return value;
}

@override
Expand Down
12 changes: 12 additions & 0 deletions lib/src/scripting_api/data_schema_value.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2023 Contributors to the Eclipse Foundation. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// SPDX-License-Identifier: BSD-3-Clause

/// Value corresponding to a WoT DataSchema as specified in [section 7.1]
/// of the [WoT Scripting API] specification.
///
/// [section 7.1]: https://www.w3.org/TR/wot-scripting-api/#the-interactioninput-type
/// [WoT Scripting API]: https://www.w3.org/TR/wot-scripting-api
typedef DataSchemaValue = Object?;
4 changes: 2 additions & 2 deletions lib/src/scripting_api/interaction_output.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:typed_data';

import '../definitions/data_schema.dart';
import '../definitions/form.dart';
import 'data_schema_value.dart';

/// Exposes the data obtained by Thing interactions.
///
Expand All @@ -33,7 +34,6 @@ abstract interface class InteractionOutput {
/// of the [InteractionOutput].
Future<ByteBuffer> arrayBuffer();

// TODO(JKRhb): Replace with some kind of DataSchemaValue
/// The parsed value of the [InteractionOutput].
Future<Object?> value();
Future<DataSchemaValue> value();
}

0 comments on commit 94d6a9b

Please sign in to comment.