From df07ca20e4d65f7baa3d6118976aba9bcf3252aa Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 18 Oct 2021 17:55:16 -0700 Subject: [PATCH] First part of #301 implementation, for Smile --- .../smile/databind/SmileMapper.java | 82 ++++++++++++++++++- .../smile/mapper/SmileMapperTest.java | 42 ++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/databind/SmileMapper.java b/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/databind/SmileMapper.java index d09c33578..ead7f2fdc 100644 --- a/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/databind/SmileMapper.java +++ b/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/databind/SmileMapper.java @@ -1,10 +1,14 @@ package com.fasterxml.jackson.dataformat.smile.databind; import com.fasterxml.jackson.core.Version; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.cfg.MapperBuilder; + import com.fasterxml.jackson.dataformat.smile.PackageVersion; import com.fasterxml.jackson.dataformat.smile.SmileFactory; +import com.fasterxml.jackson.dataformat.smile.SmileGenerator; +import com.fasterxml.jackson.dataformat.smile.SmileParser; /** * Specialized {@link ObjectMapper} to use with CBOR format backend. @@ -17,14 +21,89 @@ public class SmileMapper extends ObjectMapper /** * Base implementation for "Vanilla" {@link ObjectMapper}, used with - * CBOR backend. + * Smile backend. * * @since 2.10 */ public static class Builder extends MapperBuilder { + protected final SmileFactory _streamFactory; // since 2.14 + public Builder(SmileMapper m) { super(m); + _streamFactory = m.getFactory(); + } + + /* + /****************************************************************** + /* Format features + /****************************************************************** + */ + + /** + * @since 2.14 + */ + public Builder enable(SmileParser.Feature... features) { + for (SmileParser.Feature f : features) { + _streamFactory.enable(f); + } + return this; + } + + /** + * @since 2.14 + */ + public Builder disable(SmileParser.Feature... features) { + for (SmileParser.Feature f : features) { + _streamFactory.disable(f); + } + return this; + } + + /** + * @since 2.14 + */ + public Builder configure(SmileParser.Feature f, boolean state) + { + if (state) { + _streamFactory.enable(f); + } else { + _streamFactory.disable(f); + } + return this; + } + + /** + * @since 2.14 + */ + public Builder enable(SmileGenerator.Feature... features) { + for (SmileGenerator.Feature f : features) { + _streamFactory.enable(f); + } + return this; + } + + /** + * @since 2.14 + */ + public Builder disable(SmileGenerator.Feature... features) { + for (SmileGenerator.Feature f : features) { + _streamFactory.disable(f); + } + return this; + } + + /** + * @since 2.14 + */ + public Builder configure(SmileGenerator.Feature f, boolean state) + { + if (state) { + _streamFactory.enable(f); + } else { + _streamFactory.disable(f); + } + return this; } } @@ -46,7 +125,6 @@ protected SmileMapper(SmileMapper src) { super(src); } - @SuppressWarnings("unchecked") public static SmileMapper.Builder builder() { return new Builder(new SmileMapper()); } diff --git a/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/mapper/SmileMapperTest.java b/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/mapper/SmileMapperTest.java index cca7ae22c..2f901ef05 100644 --- a/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/mapper/SmileMapperTest.java +++ b/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/mapper/SmileMapperTest.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.core.exc.StreamReadException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -18,6 +19,9 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.dataformat.smile.BaseTestForSmile; import com.fasterxml.jackson.dataformat.smile.SmileFactory; +import com.fasterxml.jackson.dataformat.smile.SmileGenerator; +import com.fasterxml.jackson.dataformat.smile.SmileParser; +import com.fasterxml.jackson.dataformat.smile.databind.SmileMapper; public class SmileMapperTest extends BaseTestForSmile { @@ -168,4 +172,42 @@ private byte[] _generateHugeDoc(SmileFactory f) throws IOException g.close(); return b.toByteArray(); } + + /* + /********************************************************** + /* Tests for [dataformats-binary#301] + /********************************************************** + */ + + public void testStreamingFeaturesViaMapper() throws Exception + { + SmileMapper mapperWithHeaders = SmileMapper.builder() + .enable(SmileGenerator.Feature.WRITE_HEADER) + .enable(SmileParser.Feature.REQUIRE_HEADER) + .build(); + byte[] encodedWithHeader = mapperWithHeaders.writeValueAsBytes("foo"); + assertEquals(8, encodedWithHeader.length); + + SmileMapper mapperNoHeaders = SmileMapper.builder() + .disable(SmileGenerator.Feature.WRITE_HEADER) + .disable(SmileParser.Feature.REQUIRE_HEADER) + .build(); + byte[] encodedNoHeader = mapperNoHeaders.writeValueAsBytes("foo"); + assertEquals(4, encodedNoHeader.length); + + // And then see that we can parse; with header always + assertEquals("foo", mapperWithHeaders.readValue(encodedWithHeader, Object.class)); + assertEquals("foo", mapperNoHeaders.readValue(encodedWithHeader, Object.class)); + + // without if not required + assertEquals("foo", mapperNoHeaders.readValue(encodedNoHeader, Object.class)); + + // But the reverse will fail + try { + mapperWithHeaders.readValue(encodedNoHeader, Object.class); + fail("Should not pass"); + } catch (StreamReadException e) { + verifyException(e, "Input does not start with Smile format header"); + } + } }