### ----------------------------------------------------
### -- CBOR::Simple
### -- Licenses: Artistic-2.0
### -- Authors: Geoffrey Broadwell
### -- File: t/04-tags.rakutest
### ----------------------------------------------------
use Test;
use lib $*PROGRAM.sibling('lib');
use CodecMatches;

use CBOR::Simple;


plan 39;


# TAGGED VALUES

decodes-to DateTime.new("2013-03-21T20:04:00Z"),
           'c074323031332d30332d32315432303a30343a30305a';
matches Instant.from-posix(1363896240),   'c11a514b67b0';
matches Instant.from-posix(1363896240.5), 'c1fb41d452d9ec200000';

# RFC 8943 date extension tests adapted from
# https://www.rfc-editor.org/rfc/rfc8943.html#name-example-date-representation
matches    Date.new('1940-10-09'), 'd8643929b3';
matches    Date.new('1980-12-08'), 'd864190f9a';
decodes-to Date.new('1940-10-09'), 'd903ec6a313934302d31302d3039';
decodes-to Date.new('1980-12-08'), 'd903ec6a313938302d31322d3038';

# Decimal Fraction/Bigfloat tests from https://tools.ietf.org/html/rfc8949#section-3.4.4
decodes-to 273.15, 'c48221196ab3';
decodes-to   1.5,  'c582203';

# Tag 24/63: Lazily-decoded CBOR data item/Sequence
my $value = cbor-encode(42);
my $lazy  = CBOR::Simple::Tagged.new(:tag-number(24), :$value);
my $seq   = CBOR::Simple::Tagged.new(:tag-number(63), :$value);
matches $lazy, 'd81842182a';
matches $seq,  'd83f42182a';

# Extension tag 30: Rational number
# First test from http://peteroupc.github.io/CBOR/rational.html, the rest by me
matches 1/3,   'd81e820103';

matches 3/7,   'd81e820307';
matches -4/11, 'd81e82230b';
matches Rat.new(    18446744073709551614, 18446744073709551615),
        'd81e821bfffffffffffffffe1bffffffffffffffff';
matches FatRat.new( 18446744073709551615, 18446744073709551616),
        'd81e821bffffffffffffffffc249010000000000000000';
matches Rat.new(   -18446744073709551614, 18446744073709551615),
        'd81e823bfffffffffffffffd1bffffffffffffffff';
matches FatRat.new(-18446744073709551615, 18446744073709551616),
        'd81e823bfffffffffffffffec249010000000000000000';

# Extension tag 31: Absent values
# Tests from https://github.com/svaarala/cbor-specs/blob/master/cbor-absent-tag.rst
my @with-nils = ['foo', 1, 2, 'bar'];
@with-nils.BIND-POS($_, Nil) for 1..2;
encodes-to @with-nils, '8463666f6fd81ff7d81ff763626172';

my $compiler   = $*RAKU.compiler;
my $can-eqv-Mu = $compiler.name eq 'rakudo' && $compiler.version >= v2021.06;
if $can-eqv-Mu {
    decodes-to ['foo', Mu, Mu, 'bar'], '8463666f6ff7f763626172';
}
else {
    skip "Cannot run absent values test due to old compiler; requires Rakudo v2021.06 minimum";
}

# Extension tag 258: Set
matches (1, 2, 3).Set, 'd9010283010203';
matches < a b c >.Set, 'd9010283616161626163';

# Extension tag 259: Object-keyed Map; tests adapted from
# https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md
decodes-to (my Any %{Mu} = k1 => "v1", k2 => "v2" ),
           'D90103A2626B31627631626B32627632';
# decodes-to (my Any %{Mu} = 1942 => "v1", k2 => "v2", [1, 2, 3] => "v3" ),
#            'D90103A3190796627631626B3262763283010203627633';
my $hex     = 'D90103A3190796627631626B3262763283010203627633';
my $decoded = cbor-decode(hex-decode($hex));
isa-ok $decoded, Map, "decodes to a Map";
isnt $decoded.keyof.^name, 'Str', "does not have string keys";
is $decoded.AT-KEY(1942), 'v1', "has numeric key";
is $decoded.AT-KEY('k2'), 'v2', "has string key";
my $first = $decoded.keys.first(* eqv [1, 2, 3]);
is $decoded.AT-KEY($first), 'v3', "has array key";

# Extension tag 25441: Capture
# Tests from https://github.com/japhb/cbor-specs/blob/main/capture.md#examples
matches \(),                     'd9636180';
matches \(1, 3),                 'd9636181820103';
matches \(6, 9, -4),             'd963618183060923';
matches \(0, 2, :normalize),     'd9636182820002a1696e6f726d616c697a65f5';
matches \(1, 2, 3, :!normalize), 'd963618283010203a1696e6f726d616c697a65f4';

matches    \(name => "Diwali", year => 2018),
           'd9636181a2646e616d6566446977616c6964796561721907e2';

decodes-to \(name => "Diwali", year => 2018),
           'd9636181d90113a2646e616d6566446977616c6964796561721907e2';


# Tag 55799: Self-describing CBOR
decodes-to 100, 'd9d9f71864';
my $as-cbor = cbor-encode(123, :cbor-self-tag);
is-deeply $as-cbor, hex-decode('d9d9f7187b'),
          "cbor-encode(123, :cbor-self-tag) produces correct blob";

# Tag 55800: Self-describing CBOR Sequence
decodes-to 100, 'd9d9f81864';
my $as-seq = cbor-encode(123, :cbor-sequence-tag);
is-deeply $as-seq, hex-decode('d9d9f8187b'),
          "cbor-encode(123, :cbor-sequence-tag) produces correct blob";


done-testing;


