From d1a23b21f43828249ddb154562eca83a46e59978 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 23 Oct 2024 19:48:40 +0200 Subject: [PATCH 01/17] Remove internal newtonsoft json and move over to system.text.json --- .editorconfig | 12 +- Directory.Packages.props | 1 + .../Elastic.Apm.Benchmarks.csproj | 1 + .../SignatureParserBenchmark.cs | 5 +- src/Elastic.Apm.Specification/Validator.cs | 24 +- src/Elastic.Apm/Api/CapturedException.cs | 4 +- src/Elastic.Apm/Api/CapturedStackFrame.cs | 10 +- src/Elastic.Apm/Api/Cloud.cs | 4 +- src/Elastic.Apm/Api/Context.cs | 32 +- src/Elastic.Apm/Api/Http.cs | 4 +- src/Elastic.Apm/Api/IError.cs | 8 +- src/Elastic.Apm/Api/Label.cs | 25 +- src/Elastic.Apm/Api/Links.cs | 6 +- src/Elastic.Apm/Api/Node.cs | 4 +- src/Elastic.Apm/Api/Outcome.cs | 5 +- src/Elastic.Apm/Api/Request.cs | 16 +- src/Elastic.Apm/Api/Response.cs | 4 +- src/Elastic.Apm/Api/Service.cs | 4 +- src/Elastic.Apm/Api/SpanContext.cs | 13 +- src/Elastic.Apm/Api/System.cs | 8 +- src/Elastic.Apm/Api/Tracer.cs | 4 +- src/Elastic.Apm/Api/User.cs | 4 +- .../CentralConfigurationResponseParser.cs | 5 +- .../Cloud/AwsCloudMetadataProvider.cs | 23 +- .../Cloud/AzureCloudMetadataProvider.cs | 24 +- .../Cloud/GcpCloudMetadataProvider.cs | 33 +- src/Elastic.Apm/Elastic.Apm.csproj | 4 + .../Newtonsoft.Json/Bson/BsonBinaryType.cs | 48 - .../Newtonsoft.Json/Bson/BsonBinaryWriter.cs | 317 -- .../Newtonsoft.Json/Bson/BsonObjectId.cs | 60 - .../Newtonsoft.Json/Bson/BsonReader.cs | 749 ----- .../Newtonsoft.Json/Bson/BsonToken.cs | 146 - .../Newtonsoft.Json/Bson/BsonType.cs | 55 - .../Newtonsoft.Json/Bson/BsonWriter.cs | 507 --- .../Newtonsoft.Json/ConstructorHandling.cs | 48 - .../Converters/BinaryConverter.cs | 214 -- .../Converters/BsonObjectIdConverter.cs | 87 - .../Converters/CustomCreationConverter.cs | 91 - .../Converters/DataSetConverter.cs | 128 - .../Converters/DataTableConverter.cs | 257 -- .../Converters/DateTimeConverterBase.cs | 58 - .../Converters/DiscriminatedUnionConverter.cs | 301 -- .../Converters/EntityKeyMemberConverter.cs | 167 - .../Converters/ExpandoObjectConverter.cs | 165 - .../Converters/IsoDateTimeConverter.cs | 180 - .../Converters/JavaScriptDateTimeConverter.cs | 109 - .../Converters/KeyValuePairConverter.cs | 154 - .../Converters/StringEnumConverter.cs | 276 -- .../Converters/UnixDateTimeConverter.cs | 123 - .../Converters/VersionConverter.cs | 96 - .../Converters/XmlNodeConverter.cs | 2226 ------------- .../Newtonsoft.Json/DateFormatHandling.cs | 46 - .../Newtonsoft.Json/DateParseHandling.cs | 54 - .../Newtonsoft.Json/DateTimeZoneHandling.cs | 60 - .../Newtonsoft.Json/DefaultJsonNameTable.cs | 165 - .../Newtonsoft.Json/DefaultValueHandling.cs | 72 - .../Newtonsoft.Json/FloatFormatHandling.cs | 56 - .../Newtonsoft.Json/FloatParseHandling.cs | 46 - .../Newtonsoft.Json/FormatterAssemblyStyle.cs | 23 - .../Libraries/Newtonsoft.Json/Formatting.cs | 47 - .../Libraries/Newtonsoft.Json/IArrayPool.cs | 23 - .../Newtonsoft.Json/IJsonLineInfo.cs | 62 - .../Newtonsoft.Json/JsonArrayAttribute.cs | 64 - .../JsonConstructorAttribute.cs | 38 - .../Newtonsoft.Json/JsonContainerAttribute.cs | 182 -- .../Libraries/Newtonsoft.Json/JsonConvert.cs | 978 ------ .../Newtonsoft.Json/JsonConverter.cs | 151 - .../Newtonsoft.Json/JsonConverterAttribute.cs | 76 - .../JsonConverterCollection.cs | 37 - .../JsonDictionaryAttribute.cs | 51 - .../Newtonsoft.Json/JsonException.cs | 90 - .../JsonExtensionDataAttribute.cs | 39 - .../Newtonsoft.Json/JsonIgnoreAttribute.cs | 38 - .../Newtonsoft.Json/JsonNameTable.cs | 18 - .../Newtonsoft.Json/JsonObjectAttribute.cs | 102 - .../Libraries/Newtonsoft.Json/JsonPosition.cs | 158 - .../Newtonsoft.Json/JsonPropertyAttribute.cs | 227 -- .../Newtonsoft.Json/JsonReader.Async.cs | 248 -- .../Libraries/Newtonsoft.Json/JsonReader.cs | 1179 ------- .../Newtonsoft.Json/JsonReaderException.cs | 145 - .../Newtonsoft.Json/JsonRequiredAttribute.cs | 38 - .../JsonSerializationException.cs | 145 - .../Newtonsoft.Json/JsonSerializer.cs | 991 ------ .../Newtonsoft.Json/JsonSerializerSettings.cs | 452 --- .../Newtonsoft.Json/JsonTextReader.Async.cs | 1807 ---------- .../Newtonsoft.Json/JsonTextReader.cs | 2427 -------------- .../Newtonsoft.Json/JsonTextWriter.Async.cs | 1362 -------- .../Newtonsoft.Json/JsonTextWriter.cs | 860 ----- .../Libraries/Newtonsoft.Json/JsonToken.cs | 126 - .../Newtonsoft.Json/JsonValidatingReader.cs | 895 ----- .../Newtonsoft.Json/JsonWriter.Async.cs | 1799 ---------- .../Libraries/Newtonsoft.Json/JsonWriter.cs | 1547 --------- .../Newtonsoft.Json/JsonWriterException.cs | 110 - .../Newtonsoft.Json/Linq/CommentHandling.cs | 46 - .../Linq/DuplicatePropertyNameHandling.cs | 53 - .../Newtonsoft.Json/Linq/Extensions.cs | 317 -- .../Newtonsoft.Json/Linq/IJEnumerable.cs | 49 - .../Newtonsoft.Json/Linq/JArray.Async.cs | 105 - .../Libraries/Newtonsoft.Json/Linq/JArray.cs | 344 -- .../Linq/JConstructor.Async.cs | 109 - .../Newtonsoft.Json/Linq/JConstructor.cs | 214 -- .../Newtonsoft.Json/Linq/JContainer.Async.cs | 173 - .../Newtonsoft.Json/Linq/JContainer.cs | 1023 ------ .../Newtonsoft.Json/Linq/JEnumerable.cs | 125 - .../Newtonsoft.Json/Linq/JObject.Async.cs | 130 - .../Libraries/Newtonsoft.Json/Linq/JObject.cs | 752 ----- .../Newtonsoft.Json/Linq/JProperty.Async.cs | 121 - .../Newtonsoft.Json/Linq/JProperty.cs | 310 -- .../Linq/JPropertyDescriptor.cs | 159 - .../Linq/JPropertyKeyedCollection.cs | 212 -- .../Newtonsoft.Json/Linq/JRaw.Async.cs | 58 - .../Libraries/Newtonsoft.Json/Linq/JRaw.cs | 71 - .../Newtonsoft.Json/Linq/JToken.Async.cs | 180 - .../Libraries/Newtonsoft.Json/Linq/JToken.cs | 2307 ------------- .../Linq/JTokenEqualityComparer.cs | 64 - .../Newtonsoft.Json/Linq/JTokenReader.cs | 289 -- .../Newtonsoft.Json/Linq/JTokenType.cs | 126 - .../Linq/JTokenWriter.Async.cs | 54 - .../Newtonsoft.Json/Linq/JTokenWriter.cs | 513 --- .../Newtonsoft.Json/Linq/JValue.Async.cs | 140 - .../Libraries/Newtonsoft.Json/Linq/JValue.cs | 1048 ------ .../Newtonsoft.Json/Linq/JsonLoadSettings.cs | 74 - .../Newtonsoft.Json/Linq/JsonMergeSettings.cs | 96 - .../Linq/JsonPath/ArrayIndexFilter.cs | 37 - .../Linq/JsonPath/ArrayMultipleIndexFilter.cs | 25 - .../Linq/JsonPath/ArraySliceFilter.cs | 71 - .../Linq/JsonPath/FieldFilter.cs | 43 - .../Linq/JsonPath/FieldMultipleFilter.cs | 50 - .../Newtonsoft.Json/Linq/JsonPath/JPath.cs | 742 ----- .../Linq/JsonPath/PathFilter.cs | 64 - .../Linq/JsonPath/QueryExpression.cs | 267 -- .../Linq/JsonPath/QueryFilter.cs | 23 - .../Linq/JsonPath/QueryScanFilter.cs | 30 - .../Linq/JsonPath/RootFilter.cs | 14 - .../Linq/JsonPath/ScanFilter.cs | 39 - .../Linq/JsonPath/ScanMultipleFilter.cs | 36 - .../Linq/JsonSelectSettings.cs | 27 - .../Newtonsoft.Json/Linq/LineInfoHandling.cs | 46 - .../Linq/MergeArrayHandling.cs | 21 - .../Linq/MergeNullValueHandling.cs | 22 - .../Newtonsoft.Json/MemberSerialization.cs | 63 - .../MetadataPropertyHandling.cs | 51 - .../Newtonsoft.Json/MissingMemberHandling.cs | 46 - .../Newtonsoft.Json/NullValueHandling.cs | 52 - .../Newtonsoft.Json/ObjectCreationHandling.cs | 51 - .../PreserveReferencesHandling.cs | 65 - .../Newtonsoft.Json/ReferenceLoopHandling.cs | 51 - .../Libraries/Newtonsoft.Json/Required.cs | 56 - .../Newtonsoft.Json/Schema/Extensions.cs | 138 - .../Newtonsoft.Json/Schema/JsonSchema.cs | 358 -- .../Schema/JsonSchemaBuilder.cs | 415 --- .../Schema/JsonSchemaConstants.cs | 84 - .../Schema/JsonSchemaException.cs | 115 - .../Schema/JsonSchemaGenerator.cs | 442 --- .../Newtonsoft.Json/Schema/JsonSchemaModel.cs | 120 - .../Schema/JsonSchemaModelBuilder.cs | 167 - .../Newtonsoft.Json/Schema/JsonSchemaNode.cs | 88 - .../Schema/JsonSchemaNodeCollection.cs | 40 - .../Schema/JsonSchemaResolver.cs | 79 - .../Newtonsoft.Json/Schema/JsonSchemaType.cs | 92 - .../Schema/JsonSchemaWriter.cs | 232 -- .../Schema/UndefinedSchemaIdHandling.cs | 61 - .../Schema/ValidationEventArgs.cs | 71 - .../Schema/ValidationEventHandler.cs | 46 - .../Serialization/CachedAttributeGetter.cs | 40 - .../Serialization/CamelCaseNamingStrategy.cs | 83 - .../CamelCasePropertyNamesContractResolver.cs | 84 - .../Serialization/DefaultContractResolver.cs | 1544 --------- .../Serialization/DefaultNamingStrategy.cs | 16 - .../Serialization/DefaultReferenceResolver.cs | 75 - .../DefaultSerializationBinder.cs | 200 -- .../Serialization/DiagnosticsTraceWriter.cs | 80 - .../Serialization/DynamicValueProvider.cs | 129 - .../Serialization/ErrorContext.cs | 78 - .../Serialization/ErrorEventArgs.cs | 61 - .../Serialization/ExpressionValueProvider.cs | 116 - .../Serialization/FormatterConverter.cs | 110 - .../Serialization/IAttributeProvider.cs | 54 - .../Serialization/IContractResolver.cs | 51 - .../Serialization/IReferenceResolver.cs | 70 - .../Serialization/ISerializationBinder.cs | 55 - .../Serialization/ITraceWriter.cs | 29 - .../Serialization/IValueProvider.cs | 50 - .../Serialization/JsonArrayContract.cs | 311 -- .../Serialization/JsonContainerContract.cs | 111 - .../Serialization/JsonContract.cs | 297 -- .../Serialization/JsonDictionaryContract.cs | 234 -- .../Serialization/JsonDynamicContract.cs | 119 - .../Serialization/JsonFormatterConverter.cs | 162 - .../JsonISerializableContract.cs | 58 - .../Serialization/JsonLinqContract.cs | 46 - .../Serialization/JsonObjectContract.cs | 192 -- .../Serialization/JsonPrimitiveContract.cs | 75 - .../Serialization/JsonProperty.cs | 308 -- .../Serialization/JsonPropertyCollection.cs | 176 - .../JsonSerializerInternalBase.cs | 140 - .../JsonSerializerInternalReader.cs | 2392 -------------- .../JsonSerializerInternalWriter.cs | 1100 ------- .../Serialization/JsonSerializerProxy.cs | 276 -- .../Serialization/JsonStringContract.cs | 46 - .../Serialization/JsonTypeReflector.cs | 484 --- .../Serialization/KebabCaseNamingStrategy.cs | 83 - .../Serialization/MemoryTraceWriter.cs | 93 - .../Serialization/NamingStrategy.cs | 137 - .../Serialization/ObjectConstructor.cs | 36 - .../Serialization/OnErrorAttribute.cs | 38 - .../ReflectionAttributeProvider.cs | 73 - .../Serialization/ReflectionValueProvider.cs | 95 - .../SerializationBinderAdapter.cs | 56 - .../Serialization/SnakeCaseNamingStrategy.cs | 83 - .../Serialization/TraceJsonReader.cs | 146 - .../Serialization/TraceJsonWriter.cs | 525 --- .../Newtonsoft.Json/SerializationBinder.cs | 35 - .../Newtonsoft.Json/StringEscapeHandling.cs | 51 - .../Libraries/Newtonsoft.Json/TraceLevel.cs | 39 - .../TypeNameAssemblyFormatHandling.cs | 49 - .../Newtonsoft.Json/TypeNameHandling.cs | 74 - .../Newtonsoft.Json/Utilities/AsyncUtils.cs | 112 - .../Utilities/Base64Encoder.cs | 192 -- .../Utilities/BidirectionalDictionary.cs | 84 - .../Utilities/CollectionUtils.cs | 307 -- .../Utilities/CollectionWrapper.cs | 250 -- .../Newtonsoft.Json/Utilities/ConvertUtils.cs | 1444 -------- .../Utilities/DateTimeParser.cs | 254 -- .../Utilities/DateTimeUtils.cs | 774 ----- .../Utilities/DictionaryWrapper.cs | 593 ---- .../Newtonsoft.Json/Utilities/DynamicProxy.cs | 112 - .../Utilities/DynamicProxyMetaObject.cs | 395 --- .../DynamicReflectionDelegateFactory.cs | 376 --- .../Newtonsoft.Json/Utilities/DynamicUtils.cs | 218 -- .../Newtonsoft.Json/Utilities/EnumInfo.cs | 46 - .../Newtonsoft.Json/Utilities/EnumUtils.cs | 358 -- .../ExpressionReflectionDelegateFactory.cs | 365 --- .../Newtonsoft.Json/Utilities/FSharpUtils.cs | 207 -- .../Utilities/ILGeneratorExtensions.cs | 82 - .../Utilities/ImmutableCollectionsUtils.cs | 193 -- .../Utilities/JavaScriptUtils.cs | 580 ---- .../Utilities/JsonTokenUtils.cs | 77 - .../LateBoundReflectionDelegateFactory.cs | 107 - .../Newtonsoft.Json/Utilities/LinqBridge.cs | 2903 ----------------- .../Newtonsoft.Json/Utilities/MathUtils.cs | 126 - .../Newtonsoft.Json/Utilities/MethodBinder.cs | 343 -- .../Newtonsoft.Json/Utilities/MethodCall.cs | 32 - .../Utilities/MiscellaneousUtils.cs | 153 - .../Utilities/NullableAttributes.cs | 80 - .../Utilities/ReflectionDelegateFactory.cs | 85 - .../Utilities/ReflectionObject.cs | 147 - .../Utilities/ReflectionUtils.cs | 987 ------ .../Newtonsoft.Json/Utilities/StringBuffer.cs | 99 - .../Utilities/StringReference.cs | 90 - .../Newtonsoft.Json/Utilities/StringUtils.cs | 293 -- .../Utilities/StructMultiKey.cs | 55 - .../Utilities/ThreadSafeStore.cs | 103 - .../Utilities/TypeExtensions.cs | 630 ---- .../Utilities/ValidationUtils.cs | 41 - .../Libraries/Newtonsoft.Json/WriteState.cs | 76 - src/Elastic.Apm/Metrics/MetricSet.cs | 2 +- src/Elastic.Apm/Model/DroppedSpanStats.cs | 8 +- src/Elastic.Apm/Model/Error.cs | 16 +- src/Elastic.Apm/Model/Faas.cs | 5 +- src/Elastic.Apm/Model/LabelsDictionary.cs | 19 +- src/Elastic.Apm/Model/NoopSpan.cs | 7 +- src/Elastic.Apm/Model/NoopTransaction.cs | 8 +- src/Elastic.Apm/Model/Span.cs | 28 +- src/Elastic.Apm/Model/Transaction.cs | 31 +- src/Elastic.Apm/Report/IntakeResponse.cs | 8 +- src/Elastic.Apm/Report/PayloadSenderV2.cs | 2 +- .../Serialization/CustomJsonConverter.cs | 90 +- .../ElasticApmContractResolver.cs | 29 +- .../Serialization/LabelsJsonConverter.cs | 107 +- .../Serialization/MetricSetConverter.cs | 45 +- .../Report/Serialization/OutcomeConverter.cs | 38 - .../Serialization/PayloadItemSerializer.cs | 154 +- .../Serialization/TruncateJsonConverter.cs | 14 +- .../ServerInfo/ApmServerInfoProvider.cs | 13 +- .../CompositeDto.cs | 5 +- .../ContextDto.cs | 5 +- .../Controllers/IntakeV2EventsController.cs | 32 +- .../DroppedSpanStatsDto.cs | 9 +- .../ErrorDto.cs | 11 +- .../FaasDto.cs | 5 +- .../SpanContextDto.cs | 5 +- .../SpanDto.cs | 13 +- .../SpanLinkDto.cs | 7 +- .../TransactionDto.cs | 15 +- .../CGroupTestCasesAttribute.cs | 36 +- .../JsonFileDataAttribute.cs | 24 +- test/Elastic.Apm.Tests.Utilities/JsonUtils.cs | 34 +- .../MockPayloadSender.cs | 15 +- test/Elastic.Apm.Tests/ApiTests/ApiTests.cs | 24 +- .../ApiTests/ConvenientApiSpanTests.cs | 6 +- .../ApiTests/ConvenientApiTransactionTests.cs | 6 +- test/Elastic.Apm.Tests/DbSpanNameTests.cs | 17 +- .../DistributedTracing/BaggageTests.cs | 10 +- .../DistributedTracingTests.cs | 11 +- test/Elastic.Apm.Tests/ErrorTests.cs | 8 +- test/Elastic.Apm.Tests/FilterTests.cs | 16 +- .../HelpersTests/PlatformDetectionTests.cs | 8 +- test/Elastic.Apm.Tests/LabelTests.cs | 41 +- test/Elastic.Apm.Tests/SerializationTests.cs | 62 +- .../Elastic.Apm.Tests/ServiceResourceTests.cs | 15 +- .../TestHelpers/TestingConfigTests.cs | 2 +- .../Elastic.Apm.Tests/WildcardMatcherTests.cs | 13 +- .../DocumentItem.cs | 4 +- .../Elastic.Apm.Azure.CosmosDb.Tests.csproj | 1 - .../Elastic.Apm.Azure.ServiceBus.Tests.csproj | 1 - .../Elastic.Apm.Azure.Storage.Tests.csproj | 1 - .../AspNetCoreBasicTests.cs | 2 +- .../Controllers/HomeController.cs | 9 +- .../SampleAspNetCoreApp.csproj | 3 - .../applications/KafkaSample/Consumer.cs | 4 +- .../KafkaSample/KafkaSample.csproj | 1 - .../applications/KafkaSample/Producer.cs | 8 +- 313 files changed, 766 insertions(+), 62466 deletions(-) delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryType.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonObjectId.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonToken.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonType.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/ConstructorHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BinaryConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/CustomCreationConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataSetConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataTableConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DateTimeConverterBase.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/KeyValuePairConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/StringEnumConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/VersionConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/XmlNodeConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/DateFormatHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/DateParseHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/DateTimeZoneHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultJsonNameTable.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultValueHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatFormatHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatParseHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/FormatterAssemblyStyle.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Formatting.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/IArrayPool.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/IJsonLineInfo.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonArrayAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConstructorAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonContainerAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConvert.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterCollection.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonDictionaryAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonException.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonExtensionDataAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonIgnoreAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonNameTable.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonObjectAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPosition.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPropertyAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReaderException.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonRequiredAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializationException.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializer.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializerSettings.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonToken.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonValidatingReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriterException.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/CommentHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/DuplicatePropertyNameHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/Extensions.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/IJEnumerable.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JEnumerable.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyDescriptor.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenType.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.Async.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonLoadSettings.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonMergeSettings.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/JPath.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/RootFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonSelectSettings.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/LineInfoHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeArrayHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeNullValueHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/MemberSerialization.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/MetadataPropertyHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/MissingMemberHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/NullValueHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/ObjectCreationHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/PreserveReferencesHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/ReferenceLoopHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Required.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/Extensions.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchema.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaConstants.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaException.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModel.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNode.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaType.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventArgs.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventHandler.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCaseNamingStrategy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultContractResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultNamingStrategy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DynamicValueProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorContext.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorEventArgs.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/FormatterConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IAttributeProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IContractResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IReferenceResolver.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ISerializationBinder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ITraceWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IValueProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonArrayContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContainerContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDynamicContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonISerializableContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonLinqContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonObjectContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonProperty.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonStringContract.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonTypeReflector.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/KebabCaseNamingStrategy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/NamingStrategy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ObjectConstructor.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/OnErrorAttribute.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionAttributeProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SnakeCaseNamingStrategy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonReader.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonWriter.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/SerializationBinder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/StringEscapeHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/TraceLevel.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameAssemblyFormatHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameHandling.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/AsyncUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/Base64Encoder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionWrapper.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ConvertUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeParser.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DictionaryWrapper.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxy.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumInfo.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/FSharpUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JavaScriptUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JsonTokenUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LinqBridge.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MathUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodBinder.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodCall.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/NullableAttributes.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionObject.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringBuffer.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringReference.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StructMultiKey.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ThreadSafeStore.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/TypeExtensions.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ValidationUtils.cs delete mode 100644 src/Elastic.Apm/Libraries/Newtonsoft.Json/WriteState.cs delete mode 100644 src/Elastic.Apm/Report/Serialization/OutcomeConverter.cs diff --git a/.editorconfig b/.editorconfig index c5c598041..5b088da58 100644 --- a/.editorconfig +++ b/.editorconfig @@ -143,12 +143,12 @@ csharp_style_var_for_built_in_types = true:error csharp_style_var_when_type_is_apparent = true:error csharp_style_var_elsewhere = true:error -csharp_style_expression_bodied_methods = true:error -csharp_style_expression_bodied_constructors = true:error -csharp_style_expression_bodied_operators = true:error -csharp_style_expression_bodied_properties = true:error -csharp_style_expression_bodied_indexers = true:error -csharp_style_expression_bodied_accessors = true:error +csharp_style_expression_bodied_methods = true:warning +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning # Suggest more modern language features when available csharp_style_pattern_matching_over_is_with_cast_check = true:error diff --git a/Directory.Packages.props b/Directory.Packages.props index 850902ccc..a9ec50b0f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -63,6 +63,7 @@ + diff --git a/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj b/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj index 332e83070..3f60f1a9a 100644 --- a/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj +++ b/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj @@ -10,6 +10,7 @@ + diff --git a/benchmarks/Elastic.Apm.Benchmarks/SignatureParserBenchmark.cs b/benchmarks/Elastic.Apm.Benchmarks/SignatureParserBenchmark.cs index 384d77a40..12c48d945 100644 --- a/benchmarks/Elastic.Apm.Benchmarks/SignatureParserBenchmark.cs +++ b/benchmarks/Elastic.Apm.Benchmarks/SignatureParserBenchmark.cs @@ -9,9 +9,10 @@ using System.Reflection; using System.Text; using BenchmarkDotNet.Attributes; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; + using Elastic.Apm.Model; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace Elastic.Apm.Benchmarks { diff --git a/src/Elastic.Apm.Specification/Validator.cs b/src/Elastic.Apm.Specification/Validator.cs index 64a0ee847..5d8ba521c 100644 --- a/src/Elastic.Apm.Specification/Validator.cs +++ b/src/Elastic.Apm.Specification/Validator.cs @@ -11,13 +11,13 @@ using System.Reflection; using System.Runtime.Serialization; using System.Text; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading.Tasks; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Report.Serialization; using ICSharpCode.SharpZipLib.Tar; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; using NJsonSchema; namespace Elastic.Apm.Specification @@ -261,30 +261,16 @@ private async Task ValidateAsync(Type type, string specifi /// private static ImplementationProperty[] GetProperties(Type specType) { - var resolver = new ElasticApmContractResolver(); - JsonObjectContract contract; - - try - { - // the json schema may indicate a type is an "object", but the agent may model it in some other way - // e.g. samples on metricset is modelled as a collection. In these scenarios, we won't be dealing with - // an object contract and won't be able to statically determine validity of the type to the schema through reflection. - // The only way to validate these against the schema is to serialize the types. - contract = (JsonObjectContract)resolver.ResolveContract(specType); - } - catch (InvalidCastException e) - { - throw new ContractResolveException(e.Message); - } + var contract = PayloadItemSerializer.Default.GetTypeInfo(specType); var specProperties = new List(contract.Properties.Count); foreach (var jsonProperty in contract.Properties) { - if (jsonProperty.Ignored) + if (jsonProperty.AttributeProvider!.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Any()) continue; - var implementationProperty = new ImplementationProperty(jsonProperty.PropertyName, jsonProperty.PropertyType, specType); - var maxLength = (MaxLengthAttribute)jsonProperty.AttributeProvider?.GetAttributes(typeof(MaxLengthAttribute), true).FirstOrDefault(); + var implementationProperty = new ImplementationProperty(jsonProperty.Name, jsonProperty.PropertyType, specType); + var maxLength = (MaxLengthAttribute)jsonProperty.AttributeProvider?.GetCustomAttributes(typeof(MaxLengthAttribute), true).FirstOrDefault(); if (maxLength != null) implementationProperty.MaxLength = maxLength.Length; diff --git a/src/Elastic.Apm/Api/CapturedException.cs b/src/Elastic.Apm/Api/CapturedException.cs index e4cf5080a..958a3a193 100644 --- a/src/Elastic.Apm/Api/CapturedException.cs +++ b/src/Elastic.Apm/Api/CapturedException.cs @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -40,7 +40,7 @@ public class CapturedException /// /// Stacktrace information of the captured exception. /// - [JsonProperty("stacktrace")] + [JsonPropertyName("stacktrace")] public List StackTrace { get; set; } /// diff --git a/src/Elastic.Apm/Api/CapturedStackFrame.cs b/src/Elastic.Apm/Api/CapturedStackFrame.cs index 569bb470a..bfc970d76 100644 --- a/src/Elastic.Apm/Api/CapturedStackFrame.cs +++ b/src/Elastic.Apm/Api/CapturedStackFrame.cs @@ -2,7 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Elastic.Apm.Api { @@ -11,13 +11,13 @@ public class CapturedStackFrame /// /// The absolute path of the file involved in the stack frame. /// - [JsonProperty("abs_path")] + [JsonPropertyName("abs_path")] public string AbsPath { get; set; } - [JsonProperty("classname")] + [JsonPropertyName("classname")] public string ClassName { get; set; } - [JsonProperty("filename")] + [JsonPropertyName("filename")] public string FileName { get; set; } public string Function { get; set; } @@ -26,7 +26,7 @@ public class CapturedStackFrame /// The line number of code part of the stack frame. /// Zero value means the actual line number could not have been obtained. /// - [JsonProperty("lineno")] + [JsonPropertyName("lineno")] public int LineNo { get; set; } public string Module { get; set; } diff --git a/src/Elastic.Apm/Api/Cloud.cs b/src/Elastic.Apm/Api/Cloud.cs index aa9bdbe27..1c53ffe30 100644 --- a/src/Elastic.Apm/Api/Cloud.cs +++ b/src/Elastic.Apm/Api/Cloud.cs @@ -3,8 +3,8 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -19,7 +19,7 @@ public class Cloud public CloudInstance Instance { get; set; } [MaxLength] - [JsonProperty("availability_zone")] + [JsonPropertyName("availability_zone")] public string AvailabilityZone { get; set; } public CloudMachine Machine { get; set; } diff --git a/src/Elastic.Apm/Api/Context.cs b/src/Elastic.Apm/Api/Context.cs index 254d70d6e..9e4d294e1 100644 --- a/src/Elastic.Apm/Api/Context.cs +++ b/src/Elastic.Apm/Api/Context.cs @@ -4,7 +4,10 @@ using System; using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Linq; +using System.Text.Json.Serialization; +using System.Threading; +using Elastic.Apm.Helpers; using Elastic.Apm.Model; using Elastic.Apm.Report.Serialization; @@ -12,20 +15,22 @@ namespace Elastic.Apm.Api { public class Context { - private Lazy> _custom = new(); + private Lazy> _custom = new(LazyThreadSafetyMode.ExecutionAndPublication); [JsonConverter(typeof(CustomJsonConverter))] public Dictionary Custom => _custom.Value; - internal Lazy InternalLabels = new(); + [JsonPropertyName("tags"), JsonInclude] + [JsonConverter(typeof(LabelsJsonConverter))] + internal LabelsDictionary InternalLabels { get; set; } = new(); /// /// /// [Obsolete( "Instead of this dictionary, use the `SetLabel` method which supports more types than just string. This property will be removed in a future release.")] - [JsonProperty("tags")] - public Dictionary Labels => InternalLabels.Value; + [JsonIgnore] + public Dictionary Labels => InternalLabels; /// /// Holds details related to message receiving and publishing if the captured event integrates with a messaging system @@ -53,7 +58,7 @@ public class Context /// Service related information can be sent per event. Provided information will override the more generic information from /// metadata, non provided fields will be set according to the metadata information. /// - [JsonProperty("service")] + [JsonPropertyName("service"), JsonInclude] internal Service Service { get; set; } public User User { get; set; } @@ -69,15 +74,12 @@ internal Context DeepCopy() newItem._custom.Value[item.Key] = item.Value; } - newItem.InternalLabels = new Lazy(); - if (InternalLabels.IsValueCreated) - { - foreach (var item in InternalLabels.Value.InnerDictionary) - newItem.InternalLabels.Value.InnerDictionary[item.Key] = item.Value; + newItem.InternalLabels = new LabelsDictionary(); + foreach (var item in InternalLabels.InnerDictionary) + newItem.InternalLabels.InnerDictionary[item.Key] = item.Value; - foreach (var item in InternalLabels.Value) - newItem.InternalLabels.Value[item.Key] = item.Value; - } + foreach (var item in InternalLabels) + newItem.InternalLabels[item.Key] = item.Value; newItem.Request = Request?.DeepCopy(); newItem.Response = Response?.DeepCopy(); @@ -90,7 +92,7 @@ internal Context DeepCopy() /// See /// the relevant Json.NET Documentation /// - public bool ShouldSerializeLabels() => InternalLabels.IsValueCreated && InternalLabels.Value.MergedDictionary.Count > 0; + public bool ShouldSerializeLabels() => InternalLabels.MergedDictionary.Count > 0; public bool ShouldSerializeCustom() => _custom.IsValueCreated && Custom.Count > 0; } diff --git a/src/Elastic.Apm/Api/Http.cs b/src/Elastic.Apm/Api/Http.cs index 3001f47b6..85329399d 100644 --- a/src/Elastic.Apm/Api/Http.cs +++ b/src/Elastic.Apm/Api/Http.cs @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information using System; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -26,7 +26,7 @@ public class Http /// internal Uri OriginalUrl => _originalUrl; - [JsonProperty("status_code")] + [JsonPropertyName("status_code")] public int StatusCode { get; set; } /// diff --git a/src/Elastic.Apm/Api/IError.cs b/src/Elastic.Apm/Api/IError.cs index 5bee5569b..2bf6b5cd5 100644 --- a/src/Elastic.Apm/Api/IError.cs +++ b/src/Elastic.Apm/Api/IError.cs @@ -3,8 +3,8 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -68,7 +68,7 @@ public ErrorLog(string message) /// /// The name of the logger instance used. /// - [JsonProperty("logger_name")] + [JsonPropertyName("logger_name")] [MaxLength] public string LoggerName { get; set; } @@ -83,11 +83,11 @@ public ErrorLog(string message) /// together. /// The string is not interpreted, so feel free to use whichever placeholders makes sense in the client language." /// - [JsonProperty("param_message")] + [JsonPropertyName("param_message")] [MaxLength] public string ParamMessage { get; set; } - [JsonProperty("stacktrace")] + [JsonPropertyName("stacktrace")] public List StackTrace { get; set; } } } diff --git a/src/Elastic.Apm/Api/Label.cs b/src/Elastic.Apm/Api/Label.cs index aedf760f6..698e454dc 100644 --- a/src/Elastic.Apm/Api/Label.cs +++ b/src/Elastic.Apm/Api/Label.cs @@ -3,6 +3,8 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Globalization; + namespace Elastic.Apm.Api { /// @@ -25,16 +27,27 @@ public class Label public object Value { get; } - public static implicit operator Label(string value) => new Label(value); + public static implicit operator Label(string value) => new(value); + + public static implicit operator Label(bool value) => new(value); - public static implicit operator Label(bool value) => new Label(value); + public static implicit operator Label(double value) => new(value); - public static implicit operator Label(double value) => new Label(value); + public static implicit operator Label(int value) => new(value); - public static implicit operator Label(int value) => new Label(value); + public static implicit operator Label(long value) => new(value); - public static implicit operator Label(long value) => new Label(value); + public static implicit operator Label(decimal value) => new(value); - public static implicit operator Label(decimal value) => new Label(value); + public override string ToString() => Value switch + { + string s => s, + bool s => s.ToString(CultureInfo.InvariantCulture), + double s => s.ToString(CultureInfo.InvariantCulture), + int s => s.ToString(CultureInfo.InvariantCulture), + long s => s.ToString(CultureInfo.InvariantCulture), + decimal s => s.ToString(CultureInfo.InvariantCulture), + _ => Value.ToString() + }; } } diff --git a/src/Elastic.Apm/Api/Links.cs b/src/Elastic.Apm/Api/Links.cs index 625f78227..811f673ab 100644 --- a/src/Elastic.Apm/Api/Links.cs +++ b/src/Elastic.Apm/Api/Links.cs @@ -3,8 +3,8 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -20,11 +20,11 @@ public SpanLink(string spanId, string traceId) TraceId = traceId; } - [JsonProperty("span_id")] + [JsonPropertyName("span_id")] [MaxLength] public string SpanId { get; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] [MaxLength] public string TraceId { get; } } diff --git a/src/Elastic.Apm/Api/Node.cs b/src/Elastic.Apm/Api/Node.cs index 176fb368c..a93706cb6 100644 --- a/src/Elastic.Apm/Api/Node.cs +++ b/src/Elastic.Apm/Api/Node.cs @@ -2,15 +2,15 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { public class Node { - [JsonProperty("configured_name")] + [JsonPropertyName("configured_name")] [MaxLength] public string ConfiguredName { get; set; } diff --git a/src/Elastic.Apm/Api/Outcome.cs b/src/Elastic.Apm/Api/Outcome.cs index 2c3405b58..5e7a9c5a7 100644 --- a/src/Elastic.Apm/Api/Outcome.cs +++ b/src/Elastic.Apm/Api/Outcome.cs @@ -3,12 +3,11 @@ // See the LICENSE file in the project root for more information using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Converters; +using System.Text.Json.Serialization; namespace Elastic.Apm.Api { - [JsonConverter(typeof(StringEnumConverter))] + [JsonConverter(typeof(JsonStringEnumConverter))] public enum Outcome { [EnumMember(Value = "unknown")] diff --git a/src/Elastic.Apm/Api/Request.cs b/src/Elastic.Apm/Api/Request.cs index c119a069b..4e9e4201b 100644 --- a/src/Elastic.Apm/Api/Request.cs +++ b/src/Elastic.Apm/Api/Request.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -27,7 +27,7 @@ public class Request /// public Dictionary Headers { get; set; } - [JsonProperty("http_version")] + [JsonPropertyName("http_version")] [MaxLength] public string HttpVersion { get; set; } @@ -55,7 +55,7 @@ public override string ToString() => public class Socket { - [JsonProperty("remote_address")] public string RemoteAddress { get; set; } + [JsonPropertyName("remote_address")] public string RemoteAddress { get; set; } internal Socket DeepCopy() => (Socket)MemberwiseClone(); @@ -75,9 +75,13 @@ public string Full set => _full = Sanitization.TrySanitizeUrl(value, out var newValue, out _) ? newValue : value; } - [MaxLength][JsonProperty("hostname")] public string HostName { get; set; } + [MaxLength] + [JsonPropertyName("hostname")] + public string HostName { get; set; } - [MaxLength][JsonProperty("pathname")] public string PathName { get; set; } + [MaxLength] + [JsonPropertyName("pathname")] + public string PathName { get; set; } [MaxLength] public string Protocol { get; set; } @@ -93,7 +97,7 @@ public string Raw /// It is expected to have values delimited by ampersands. /// [MaxLength] - [JsonProperty("search")] + [JsonPropertyName("search")] public string Search { get; set; } internal Url DeepCopy() => (Url)MemberwiseClone(); diff --git a/src/Elastic.Apm/Api/Response.cs b/src/Elastic.Apm/Api/Response.cs index 4557cd0e3..d06a9465b 100644 --- a/src/Elastic.Apm/Api/Response.cs +++ b/src/Elastic.Apm/Api/Response.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Elastic.Apm.Api { @@ -22,7 +22,7 @@ public class Response /// /// The HTTP status code of the response. /// - [JsonProperty("status_code")] + [JsonPropertyName("status_code")] public int StatusCode { get; set; } internal Response DeepCopy() diff --git a/src/Elastic.Apm/Api/Service.cs b/src/Elastic.Apm/Api/Service.cs index 07107c7a9..6adde8191 100644 --- a/src/Elastic.Apm/Api/Service.cs +++ b/src/Elastic.Apm/Api/Service.cs @@ -5,10 +5,10 @@ using System; using System.Linq; using System.Reflection; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Config; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Logging; namespace Elastic.Apm.Api @@ -119,7 +119,7 @@ public class AgentC public string Version { get; set; } [MaxLength] - [JsonProperty("activation_method")] + [JsonPropertyName("activation_method")] public string ActivationMethod { get; set; } public override string ToString() => diff --git a/src/Elastic.Apm/Api/SpanContext.cs b/src/Elastic.Apm/Api/SpanContext.cs index c0f005795..65d7c7513 100644 --- a/src/Elastic.Apm/Api/SpanContext.cs +++ b/src/Elastic.Apm/Api/SpanContext.cs @@ -4,15 +4,18 @@ using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Model; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Api { public class SpanContext { - internal readonly Lazy InternalLabels = new Lazy(); + [JsonPropertyName("tags"), JsonInclude] + [JsonConverter(typeof(LabelsJsonConverter))] + internal LabelsDictionary InternalLabels { get; set; } = new(); public Database Db { get; set; } public Destination Destination { get; set; } @@ -22,17 +25,17 @@ public class SpanContext /// /// /// - [JsonProperty("tags")] [Obsolete( "Instead of this dictionary, use the `SetLabel` method which supports more types than just string. This property will be removed in a future release.")] - public Dictionary Labels => InternalLabels.Value; + [JsonIgnore] + public Dictionary Labels => InternalLabels; /// /// Method to conditionally serialize - serialize only when there is at least one label. /// See /// the relevant Json.NET Documentation /// - public bool ShouldSerializeLabels() => InternalLabels.IsValueCreated && InternalLabels.Value.MergedDictionary.Count > 0; + public bool ShouldSerializeLabels() => InternalLabels.MergedDictionary.Count > 0; public SpanService Service { get; set; } diff --git a/src/Elastic.Apm/Api/System.cs b/src/Elastic.Apm/Api/System.cs index 6545ce6f2..8dffc539e 100644 --- a/src/Elastic.Apm/Api/System.cs +++ b/src/Elastic.Apm/Api/System.cs @@ -3,10 +3,10 @@ // See the LICENSE file in the project root for more information using System; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Api.Kubernetes; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -21,7 +21,7 @@ public class System /// It will be used as the event's hostname if is not present. /// [MaxLength] - [JsonProperty("detected_hostname")] + [JsonPropertyName("detected_hostname")] public string DetectedHostName { get; set; } /// @@ -29,14 +29,14 @@ public class System /// If given, it is used as the event's hostname. /// [MaxLength] - [JsonProperty("configured_hostname")] + [JsonPropertyName("configured_hostname")] public string ConfiguredHostName { get; set; } /// /// The hostname configured by the user, if configured, otherwise the detected hostname. /// [MaxLength] - [JsonProperty("hostname")] + [JsonPropertyName("hostname")] [Obsolete("Deprecated. Use " + nameof(ConfiguredHostName))] public string HostName { diff --git a/src/Elastic.Apm/Api/Tracer.cs b/src/Elastic.Apm/Api/Tracer.cs index d91fc97ee..cb0110d5c 100644 --- a/src/Elastic.Apm/Api/Tracer.cs +++ b/src/Elastic.Apm/Api/Tracer.cs @@ -80,8 +80,8 @@ private Transaction StartTransactionInternal(string name, string type, Distribut var currentConfig = _configurationProvider.CurrentSnapshot; var retVal = new Transaction(_logger, name, type, new Sampler(currentConfig.TransactionSampleRate), distributedTracingData , _sender, currentConfig, CurrentExecutionSegmentsContainer, _apmServerInfo, _breakdownMetricsProvider, ignoreActivity, timestamp, id, - traceId: traceId, links: links, current: current) - { Service = _service }; + traceId: traceId, links: links, current: current); + retVal.Context.Service = _service; _logger?.Debug()?.Log("Starting {TransactionValue}", retVal); return retVal; diff --git a/src/Elastic.Apm/Api/User.cs b/src/Elastic.Apm/Api/User.cs index 51d81361e..4f26e85fb 100644 --- a/src/Elastic.Apm/Api/User.cs +++ b/src/Elastic.Apm/Api/User.cs @@ -2,9 +2,9 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Api { @@ -17,7 +17,7 @@ public class User public string Id { get; set; } [MaxLength] - [JsonProperty("username")] + [JsonPropertyName("username")] public string UserName { get; set; } public override string ToString() => diff --git a/src/Elastic.Apm/BackendComm/CentralConfig/CentralConfigurationResponseParser.cs b/src/Elastic.Apm/BackendComm/CentralConfig/CentralConfigurationResponseParser.cs index 4ab8768ce..4d5e30174 100644 --- a/src/Elastic.Apm/BackendComm/CentralConfig/CentralConfigurationResponseParser.cs +++ b/src/Elastic.Apm/BackendComm/CentralConfig/CentralConfigurationResponseParser.cs @@ -8,9 +8,10 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Text.Json.Serialization; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Logging; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.BackendComm.CentralConfig { @@ -42,7 +43,7 @@ string httpResponseBody if (httpResponse?.Headers?.ETag == null) throw new CentralConfigurationFetcher.FailedToFetchConfigException("Response from APM Server doesn't have ETag header", waitInfo); - var keyValues = JsonConvert.DeserializeObject>(httpResponseBody); + var keyValues = PayloadItemSerializer.Default.Deserialize>(httpResponseBody); var centralConfigReader = ParseConfigPayload(httpResponse, new CentralConfigPayload(keyValues)); return (centralConfigReader, waitInfo); diff --git a/src/Elastic.Apm/Cloud/AwsCloudMetadataProvider.cs b/src/Elastic.Apm/Cloud/AwsCloudMetadataProvider.cs index 1ec6afef3..a8b9734b9 100644 --- a/src/Elastic.Apm/Cloud/AwsCloudMetadataProvider.cs +++ b/src/Elastic.Apm/Cloud/AwsCloudMetadataProvider.cs @@ -7,11 +7,12 @@ using System.IO; using System.Net.Http; using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Logging; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Cloud { @@ -56,28 +57,24 @@ internal AwsCloudMetadataProvider(IApmLogger logger, HttpMessageHandler handler) if (string.IsNullOrWhiteSpace(awsToken)) return null; - JObject metadata; + JsonObject metadata; using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, MetadataUri)) { requestMessage.Headers.Add("X-aws-ec2-metadata-token", awsToken); var responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false); using var stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); - using var streamReader = new StreamReader(stream, Encoding.UTF8); - using var jsonReader = new JsonTextReader(streamReader); - - var serializer = new JsonSerializer(); - metadata = serializer.Deserialize(jsonReader); + metadata = PayloadItemSerializer.Default.Deserialize(stream); } return new Api.Cloud { - Account = new CloudAccount { Id = metadata["accountId"].Value() }, - Instance = new CloudInstance { Id = metadata["instanceId"].Value() }, - AvailabilityZone = metadata["availabilityZone"]?.Value(), - Machine = new CloudMachine { Type = metadata["instanceType"].Value() }, + Account = new CloudAccount { Id = metadata["accountId"]?.GetValue() }, + Instance = new CloudInstance { Id = metadata["instanceId"]?.GetValue() }, + AvailabilityZone = metadata["availabilityZone"]?.GetValue(), + Machine = new CloudMachine { Type = metadata["instanceType"]?.GetValue() }, Provider = Provider, - Region = metadata["region"].Value() + Region = metadata["region"]?.GetValue() }; } diff --git a/src/Elastic.Apm/Cloud/AzureCloudMetadataProvider.cs b/src/Elastic.Apm/Cloud/AzureCloudMetadataProvider.cs index 7c18559b1..8204a822e 100644 --- a/src/Elastic.Apm/Cloud/AzureCloudMetadataProvider.cs +++ b/src/Elastic.Apm/Cloud/AzureCloudMetadataProvider.cs @@ -7,11 +7,11 @@ using System.IO; using System.Net.Http; using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Logging; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Cloud { @@ -45,29 +45,25 @@ internal AzureCloudMetadataProvider(IApmLogger logger, HttpMessageHandler handle var client = new HttpClient(_handler, false) { Timeout = TimeSpan.FromSeconds(3) }; try { - JObject metadata; + JsonObject metadata; using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, MetadataUri)) { requestMessage.Headers.Add("Metadata", "true"); var responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false); using var stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); - using var streamReader = new StreamReader(stream, Encoding.UTF8); - using var jsonReader = new JsonTextReader(streamReader); - - var serializer = new JsonSerializer(); - metadata = serializer.Deserialize(jsonReader); + metadata = PayloadItemSerializer.Default.Deserialize(stream); } return new Api.Cloud { - Account = new CloudAccount { Id = metadata["subscriptionId"].Value() }, - Instance = new CloudInstance { Id = metadata["vmId"].Value(), Name = metadata["name"].Value() }, - Project = new CloudProject { Name = metadata["resourceGroupName"].Value() }, - AvailabilityZone = metadata["zone"]?.Value(), - Machine = new CloudMachine { Type = metadata["vmSize"].Value() }, + Account = new CloudAccount { Id = metadata["subscriptionId"]?.GetValue() }, + Instance = new CloudInstance { Id = metadata["vmId"]?.GetValue(), Name = metadata["name"]?.GetValue() }, + Project = new CloudProject { Name = metadata["resourceGroupName"]?.GetValue() }, + AvailabilityZone = metadata["zone"]?.GetValue(), + Machine = new CloudMachine { Type = metadata["vmSize"]?.GetValue() }, Provider = Provider, - Region = metadata["location"].Value() + Region = metadata["location"]?.GetValue() }; } catch (Exception e) diff --git a/src/Elastic.Apm/Cloud/GcpCloudMetadataProvider.cs b/src/Elastic.Apm/Cloud/GcpCloudMetadataProvider.cs index 057984c81..597d56021 100644 --- a/src/Elastic.Apm/Cloud/GcpCloudMetadataProvider.cs +++ b/src/Elastic.Apm/Cloud/GcpCloudMetadataProvider.cs @@ -8,11 +8,11 @@ using System.IO; using System.Net.Http; using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Logging; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Cloud { @@ -46,42 +46,41 @@ internal GcpCloudMetadataProvider(IApmLogger logger, HttpMessageHandler handler) var client = new HttpClient(_handler, false) { Timeout = TimeSpan.FromSeconds(3) }; try { - JObject metadata; + JsonObject metadata; using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, MetadataUri)) { requestMessage.Headers.Add("Metadata-Flavor", "Google"); var responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false); using var stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); - using var streamReader = new StreamReader(stream, Encoding.UTF8); - using var jsonReader = new JsonTextReader(streamReader); - - var serializer = new JsonSerializer(); - metadata = serializer.Deserialize(jsonReader); + metadata = PayloadItemSerializer.Default.Deserialize(stream); } - var zoneParts = metadata["instance"]["zone"].Value().Split('/'); - var availabilityZone = zoneParts[zoneParts.Length - 1]; + var zoneParts = metadata["instance"]?["zone"]?.GetValue()?.Split('/'); + var availabilityZone = zoneParts is { Length: > 0 } ? zoneParts[zoneParts.Length - 1] : null; - var lastHyphen = availabilityZone.LastIndexOf('-'); - var region = lastHyphen > -1 + var lastHyphen = availabilityZone?.LastIndexOf('-') ?? -1; + var region = availabilityZone != null && lastHyphen > -1 ? availabilityZone.Substring(0, lastHyphen) : availabilityZone; - var machineTypeParts = metadata["instance"]["machineType"].Value().Split('/'); - var machineType = machineTypeParts[machineTypeParts.Length - 1]; + var machineTypeParts = metadata["instance"]?["machineType"]?.GetValue()?.Split('/'); + var machineType = machineTypeParts is { Length: > 0 } ? machineTypeParts[machineTypeParts.Length - 1] : null; + var instanceId = metadata["instance"]?["id"]?.GetValue().ToString(CultureInfo.InvariantCulture); + var instanceName = metadata["instance"]?["name"]?.GetValue(); + var projectId = metadata["project"]?["projectId"]?.GetValue(); return new Api.Cloud { Instance = new CloudInstance { - Id = metadata["instance"]["id"].Value().ToString(CultureInfo.InvariantCulture), - Name = metadata["instance"]["name"].Value() + Id = instanceId, + Name = instanceName }, Project = new CloudProject { - Id = metadata["project"]["projectId"].Value() + Id = projectId }, AvailabilityZone = availabilityZone, Machine = new CloudMachine { Type = machineType }, diff --git a/src/Elastic.Apm/Elastic.Apm.csproj b/src/Elastic.Apm/Elastic.Apm.csproj index c23a8041e..dc2c55324 100644 --- a/src/Elastic.Apm/Elastic.Apm.csproj +++ b/src/Elastic.Apm/Elastic.Apm.csproj @@ -124,4 +124,8 @@ + + + + diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryType.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryType.cs deleted file mode 100644 index e5d8aed77..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryType.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - internal enum BsonBinaryType : byte - { - Binary = 0x00, - Function = 0x01, - - [Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")] - BinaryOld = 0x02, - - [Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")] - UuidOld = 0x03, - Uuid = 0x04, - Md5 = 0x05, - UserDefined = 0x80 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryWriter.cs deleted file mode 100644 index d3e7f6284..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonBinaryWriter.cs +++ /dev/null @@ -1,317 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - internal class BsonBinaryWriter - { - private static readonly Encoding Encoding = new UTF8Encoding(false); - - private readonly BinaryWriter _writer; - - public BsonBinaryWriter(BinaryWriter writer) - { - DateTimeKindHandling = DateTimeKind.Utc; - _writer = writer; - } - - private byte[] _largeByteBuffer; - - public DateTimeKind DateTimeKindHandling { get; set; } - - public void Flush() => _writer.Flush(); - - public void Close() - { -#if HAVE_STREAM_READER_WRITER_CLOSE - _writer.Close(); -#else - _writer.Dispose(); -#endif - } - - public void WriteToken(BsonToken t) - { - CalculateSize(t); - WriteTokenInternal(t); - } - - private void WriteTokenInternal(BsonToken t) - { - switch (t.Type) - { - case BsonType.Object: - { - var value = (BsonObject)t; - _writer.Write(value.CalculatedSize); - foreach (var property in value) - { - _writer.Write((sbyte)property.Value.Type); - WriteString((string)property.Name.Value, property.Name.ByteCount, null); - WriteTokenInternal(property.Value); - } - _writer.Write((byte)0); - } - break; - case BsonType.Array: - { - var value = (BsonArray)t; - _writer.Write(value.CalculatedSize); - ulong index = 0; - foreach (var c in value) - { - _writer.Write((sbyte)c.Type); - WriteString(index.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(index), null); - WriteTokenInternal(c); - index++; - } - _writer.Write((byte)0); - } - break; - case BsonType.Integer: - { - var value = (BsonValue)t; - _writer.Write(Convert.ToInt32(value.Value, CultureInfo.InvariantCulture)); - } - break; - case BsonType.Long: - { - var value = (BsonValue)t; - _writer.Write(Convert.ToInt64(value.Value, CultureInfo.InvariantCulture)); - } - break; - case BsonType.Number: - { - var value = (BsonValue)t; - _writer.Write(Convert.ToDouble(value.Value, CultureInfo.InvariantCulture)); - } - break; - case BsonType.String: - { - var value = (BsonString)t; - WriteString((string)value.Value, value.ByteCount, value.CalculatedSize - 4); - } - break; - case BsonType.Boolean: - _writer.Write(t == BsonBoolean.True); - break; - case BsonType.Null: - case BsonType.Undefined: - break; - case BsonType.Date: - { - var value = (BsonValue)t; - - long ticks = 0; - - if (value.Value is DateTime dateTime) - { - if (DateTimeKindHandling == DateTimeKind.Utc) - dateTime = dateTime.ToUniversalTime(); - else if (DateTimeKindHandling == DateTimeKind.Local) dateTime = dateTime.ToLocalTime(); - - ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, false); - } -#if HAVE_DATE_TIME_OFFSET - else - { - DateTimeOffset dateTimeOffset = (DateTimeOffset)value.Value; - ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset); - } -#endif - - _writer.Write(ticks); - } - break; - case BsonType.Binary: - { - var value = (BsonBinary)t; - - var data = (byte[])value.Value; - _writer.Write(data.Length); - _writer.Write((byte)value.BinaryType); - _writer.Write(data); - } - break; - case BsonType.Oid: - { - var value = (BsonValue)t; - - var data = (byte[])value.Value; - _writer.Write(data); - } - break; - case BsonType.Regex: - { - var value = (BsonRegex)t; - - WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null); - WriteString((string)value.Options.Value, value.Options.ByteCount, null); - } - break; - default: - throw new ArgumentOutOfRangeException(nameof(t), - "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); - } - } - - private void WriteString(string s, int byteCount, int? calculatedlengthPrefix) - { - if (calculatedlengthPrefix != null) _writer.Write(calculatedlengthPrefix.GetValueOrDefault()); - - WriteUtf8Bytes(s, byteCount); - - _writer.Write((byte)0); - } - - public void WriteUtf8Bytes(string s, int byteCount) - { - if (s != null) - { - if (byteCount <= 256) - { - if (_largeByteBuffer == null) _largeByteBuffer = new byte[256]; - - Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0); - _writer.Write(_largeByteBuffer, 0, byteCount); - } - else - { - var bytes = Encoding.GetBytes(s); - _writer.Write(bytes); - } - } - } - - private int CalculateSize(int stringByteCount) => stringByteCount + 1; - - private int CalculateSizeWithLength(int stringByteCount, bool includeSize) - { - var baseSize = includeSize - ? 5 // size bytes + terminator - : 1; // terminator - - return baseSize + stringByteCount; - } - - private int CalculateSize(BsonToken t) - { - switch (t.Type) - { - case BsonType.Object: - { - var value = (BsonObject)t; - - var bases = 4; - foreach (var p in value) - { - var size = 1; - size += CalculateSize(p.Name); - size += CalculateSize(p.Value); - - bases += size; - } - bases += 1; - value.CalculatedSize = bases; - return bases; - } - case BsonType.Array: - { - var value = (BsonArray)t; - - var size = 4; - ulong index = 0; - foreach (var c in value) - { - size += 1; - size += CalculateSize(MathUtils.IntLength(index)); - size += CalculateSize(c); - index++; - } - size += 1; - value.CalculatedSize = size; - - return value.CalculatedSize; - } - case BsonType.Integer: - return 4; - case BsonType.Long: - return 8; - case BsonType.Number: - return 8; - case BsonType.String: - { - var value = (BsonString)t; - var s = (string)value.Value; - value.ByteCount = s != null ? Encoding.GetByteCount(s) : 0; - value.CalculatedSize = CalculateSizeWithLength(value.ByteCount, value.IncludeLength); - - return value.CalculatedSize; - } - case BsonType.Boolean: - return 1; - case BsonType.Null: - case BsonType.Undefined: - return 0; - case BsonType.Date: - return 8; - case BsonType.Binary: - { - var value = (BsonBinary)t; - - var data = (byte[])value.Value; - value.CalculatedSize = 4 + 1 + data.Length; - - return value.CalculatedSize; - } - case BsonType.Oid: - return 12; - case BsonType.Regex: - { - var value = (BsonRegex)t; - var size = 0; - size += CalculateSize(value.Pattern); - size += CalculateSize(value.Options); - value.CalculatedSize = size; - - return value.CalculatedSize; - } - default: - throw new ArgumentOutOfRangeException(nameof(t), - "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonObjectId.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonObjectId.cs deleted file mode 100644 index 5a33ef8ee..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonObjectId.cs +++ /dev/null @@ -1,60 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - /// - /// Represents a BSON Oid (object id). - /// - [Obsolete( - "BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] - internal class BsonObjectId - { - /// - /// Initializes a new instance of the class. - /// - /// The Oid value. - public BsonObjectId(byte[] value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value.Length != 12) throw new ArgumentException("An ObjectId must be 12 bytes", nameof(value)); - - Value = value; - } - - /// - /// Gets or sets the value of the Oid. - /// - /// The value of the Oid. - public byte[] Value { get; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonReader.cs deleted file mode 100644 index fba966ae2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonReader.cs +++ /dev/null @@ -1,749 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - /// - /// Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data. - /// - [Obsolete( - "BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] - internal class BsonReader : JsonReader - { - private const int MaxCharBytesSize = 128; - private static readonly byte[] SeqRange1 = { 0, 127 }; // range of 1-byte sequence - private static readonly byte[] SeqRange2 = { 194, 223 }; // range of 2-byte sequence - private static readonly byte[] SeqRange3 = { 224, 239 }; // range of 3-byte sequence - private static readonly byte[] SeqRange4 = { 240, 244 }; // range of 4-byte sequence - - private readonly BinaryReader _reader; - private readonly List _stack; - - /// - /// Initializes a new instance of the class. - /// - /// The containing the BSON data to read. - public BsonReader(Stream stream) - : this(stream, false, DateTimeKind.Local) { } - - /// - /// Initializes a new instance of the class. - /// - /// The containing the BSON data to read. - public BsonReader(BinaryReader reader) - : this(reader, false, DateTimeKind.Local) { } - - /// - /// Initializes a new instance of the class. - /// - /// The containing the BSON data to read. - /// if set to true the root object will be read as a JSON array. - /// - /// The used when reading values - /// from BSON. - /// - public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) - { - ValidationUtils.ArgumentNotNull(stream, nameof(stream)); - _reader = new BinaryReader(stream); - _stack = new List(); - ReadRootValueAsArray = readRootValueAsArray; - DateTimeKindHandling = dateTimeKindHandling; - } - - /// - /// Initializes a new instance of the class. - /// - /// The containing the BSON data to read. - /// if set to true the root object will be read as a JSON array. - /// - /// The used when reading values - /// from BSON. - /// - public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - _reader = reader; - _stack = new List(); - ReadRootValueAsArray = readRootValueAsArray; - DateTimeKindHandling = dateTimeKindHandling; - } - - private BsonReaderState _bsonReaderState; - - private byte[] _byteBuffer; - private char[] _charBuffer; - private ContainerContext _currentContext; - - private BsonType _currentElementType; - - /// - /// Gets or sets the used when reading values from BSON. - /// - /// The used when reading values from BSON. - public DateTimeKind DateTimeKindHandling { get; set; } - - /// - /// Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written - /// binary. - /// - /// - /// true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, - /// false. - /// - [Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")] - public bool JsonNet35BinaryCompatibility { get; set; } - - /// - /// Gets or sets a value indicating whether the root object will be read as a JSON array. - /// - /// - /// true if the root object will be read as a JSON array; otherwise, false. - /// - public bool ReadRootValueAsArray { get; set; } - - private string ReadElement() - { - _currentElementType = ReadType(); - var elementName = ReadString(); - return elementName; - } - - /// - /// Reads the next JSON token from the underlying . - /// - /// - /// true if the next token was read successfully; false if there are no more tokens to read. - /// - public override bool Read() - { - try - { - bool success; - - switch (_bsonReaderState) - { - case BsonReaderState.Normal: - success = ReadNormal(); - break; - case BsonReaderState.ReferenceStart: - case BsonReaderState.ReferenceRef: - case BsonReaderState.ReferenceId: - success = ReadReference(); - break; - case BsonReaderState.CodeWScopeStart: - case BsonReaderState.CodeWScopeCode: - case BsonReaderState.CodeWScopeScope: - case BsonReaderState.CodeWScopeScopeObject: - case BsonReaderState.CodeWScopeScopeEnd: - success = ReadCodeWScope(); - break; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState)); - } - - if (!success) - { - SetToken(JsonToken.None); - return false; - } - - return true; - } - catch (EndOfStreamException) - { - SetToken(JsonToken.None); - return false; - } - } - - /// - /// Changes the reader's state to . - /// If is set to true, the underlying is also closed. - /// - public override void Close() - { - base.Close(); - - if (CloseInput) - { -#if HAVE_STREAM_READER_WRITER_CLOSE - _reader?.Close(); -#else - _reader?.Dispose(); -#endif - } - } - - private bool ReadCodeWScope() - { - switch (_bsonReaderState) - { - case BsonReaderState.CodeWScopeStart: - SetToken(JsonToken.PropertyName, "$code"); - _bsonReaderState = BsonReaderState.CodeWScopeCode; - return true; - case BsonReaderState.CodeWScopeCode: - // total CodeWScope size - not used - ReadInt32(); - - SetToken(JsonToken.String, ReadLengthString()); - _bsonReaderState = BsonReaderState.CodeWScopeScope; - return true; - case BsonReaderState.CodeWScopeScope: - if (CurrentState == State.PostValue) - { - SetToken(JsonToken.PropertyName, "$scope"); - return true; - } - else - { - SetToken(JsonToken.StartObject); - _bsonReaderState = BsonReaderState.CodeWScopeScopeObject; - - var newContext = new ContainerContext(BsonType.Object); - PushContext(newContext); - newContext.Length = ReadInt32(); - - return true; - } - case BsonReaderState.CodeWScopeScopeObject: - var result = ReadNormal(); - if (result && TokenType == JsonToken.EndObject) _bsonReaderState = BsonReaderState.CodeWScopeScopeEnd; - - return result; - case BsonReaderState.CodeWScopeScopeEnd: - SetToken(JsonToken.EndObject); - _bsonReaderState = BsonReaderState.Normal; - return true; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private bool ReadReference() - { - switch (CurrentState) - { - case State.ObjectStart: - { - SetToken(JsonToken.PropertyName, JsonTypeReflector.RefPropertyName); - _bsonReaderState = BsonReaderState.ReferenceRef; - return true; - } - case State.Property: - { - if (_bsonReaderState == BsonReaderState.ReferenceRef) - { - SetToken(JsonToken.String, ReadLengthString()); - return true; - } - if (_bsonReaderState == BsonReaderState.ReferenceId) - { - SetToken(JsonToken.Bytes, ReadBytes(12)); - return true; - } - throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); - } - case State.PostValue: - { - if (_bsonReaderState == BsonReaderState.ReferenceRef) - { - SetToken(JsonToken.PropertyName, JsonTypeReflector.IdPropertyName); - _bsonReaderState = BsonReaderState.ReferenceId; - return true; - } - if (_bsonReaderState == BsonReaderState.ReferenceId) - { - SetToken(JsonToken.EndObject); - _bsonReaderState = BsonReaderState.Normal; - return true; - } - throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); - } - default: - throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + CurrentState); - } - } - - private bool ReadNormal() - { - switch (CurrentState) - { - case State.Start: - { - var token = !ReadRootValueAsArray ? JsonToken.StartObject : JsonToken.StartArray; - var type = !ReadRootValueAsArray ? BsonType.Object : BsonType.Array; - - SetToken(token); - var newContext = new ContainerContext(type); - PushContext(newContext); - newContext.Length = ReadInt32(); - return true; - } - case State.Complete: - case State.Closed: - return false; - case State.Property: - { - ReadType(_currentElementType); - return true; - } - case State.ObjectStart: - case State.ArrayStart: - case State.PostValue: - var context = _currentContext; - if (context == null) - { - if (SupportMultipleContent) goto case State.Start; - - return false; - } - - var lengthMinusEnd = context.Length - 1; - - if (context.Position < lengthMinusEnd) - { - if (context.Type == BsonType.Array) - { - ReadElement(); - ReadType(_currentElementType); - return true; - } - SetToken(JsonToken.PropertyName, ReadElement()); - return true; - } - else if (context.Position == lengthMinusEnd) - { - if (ReadByte() != 0) throw JsonReaderException.Create(this, "Unexpected end of object byte value."); - - PopContext(); - if (_currentContext != null) MovePosition(context.Length); - - var endToken = context.Type == BsonType.Object ? JsonToken.EndObject : JsonToken.EndArray; - SetToken(endToken); - return true; - } - else - throw JsonReaderException.Create(this, "Read past end of current container context."); - case State.ConstructorStart: - break; - case State.Constructor: - break; - case State.Error: - break; - case State.Finished: - break; - default: - throw new ArgumentOutOfRangeException(); - } - - return false; - } - - private void PopContext() - { - _stack.RemoveAt(_stack.Count - 1); - if (_stack.Count == 0) - _currentContext = null; - else - _currentContext = _stack[_stack.Count - 1]; - } - - private void PushContext(ContainerContext newContext) - { - _stack.Add(newContext); - _currentContext = newContext; - } - - private byte ReadByte() - { - MovePosition(1); - return _reader.ReadByte(); - } - - private void ReadType(BsonType type) - { - switch (type) - { - case BsonType.Number: - var d = ReadDouble(); - - if (_floatParseHandling == FloatParseHandling.Decimal) - SetToken(JsonToken.Float, Convert.ToDecimal(d, CultureInfo.InvariantCulture)); - else - SetToken(JsonToken.Float, d); - break; - case BsonType.String: - case BsonType.Symbol: - SetToken(JsonToken.String, ReadLengthString()); - break; - case BsonType.Object: - { - SetToken(JsonToken.StartObject); - - var newContext = new ContainerContext(BsonType.Object); - PushContext(newContext); - newContext.Length = ReadInt32(); - break; - } - case BsonType.Array: - { - SetToken(JsonToken.StartArray); - - var newContext = new ContainerContext(BsonType.Array); - PushContext(newContext); - newContext.Length = ReadInt32(); - break; - } - case BsonType.Binary: - BsonBinaryType binaryType; - var data = ReadBinary(out binaryType); - - var value = binaryType != BsonBinaryType.Uuid - ? data - : (object)new Guid(data); - - SetToken(JsonToken.Bytes, value); - break; - case BsonType.Undefined: - SetToken(JsonToken.Undefined); - break; - case BsonType.Oid: - var oid = ReadBytes(12); - SetToken(JsonToken.Bytes, oid); - break; - case BsonType.Boolean: - var b = Convert.ToBoolean(ReadByte()); - SetToken(JsonToken.Boolean, b); - break; - case BsonType.Date: - var ticks = ReadInt64(); - var utcDateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks); - - DateTime dateTime; - switch (DateTimeKindHandling) - { - case DateTimeKind.Unspecified: - dateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified); - break; - case DateTimeKind.Local: - dateTime = utcDateTime.ToLocalTime(); - break; - default: - dateTime = utcDateTime; - break; - } - - SetToken(JsonToken.Date, dateTime); - break; - case BsonType.Null: - SetToken(JsonToken.Null); - break; - case BsonType.Regex: - var expression = ReadString(); - var modifiers = ReadString(); - - var regex = @"/" + expression + @"/" + modifiers; - SetToken(JsonToken.String, regex); - break; - case BsonType.Reference: - SetToken(JsonToken.StartObject); - _bsonReaderState = BsonReaderState.ReferenceStart; - break; - case BsonType.Code: - SetToken(JsonToken.String, ReadLengthString()); - break; - case BsonType.CodeWScope: - SetToken(JsonToken.StartObject); - _bsonReaderState = BsonReaderState.CodeWScopeStart; - break; - case BsonType.Integer: - SetToken(JsonToken.Integer, (long)ReadInt32()); - break; - case BsonType.TimeStamp: - case BsonType.Long: - SetToken(JsonToken.Integer, ReadInt64()); - break; - default: - throw new ArgumentOutOfRangeException(nameof(type), "Unexpected BsonType value: " + type); - } - } - - private byte[] ReadBinary(out BsonBinaryType binaryType) - { - var dataLength = ReadInt32(); - - binaryType = (BsonBinaryType)ReadByte(); - -#pragma warning disable 612,618 - // the old binary type has the data length repeated in the data for some reason - if (binaryType == BsonBinaryType.BinaryOld && !JsonNet35BinaryCompatibility) dataLength = ReadInt32(); -#pragma warning restore 612,618 - - return ReadBytes(dataLength); - } - - private string ReadString() - { - EnsureBuffers(); - - StringBuilder builder = null; - - var totalBytesRead = 0; - // used in case of left over multibyte characters in the buffer - var offset = 0; - while (true) - { - var count = offset; - byte b; - while (count < MaxCharBytesSize && (b = _reader.ReadByte()) > 0) _byteBuffer[count++] = b; - var byteCount = count - offset; - totalBytesRead += byteCount; - - if (count < MaxCharBytesSize && builder == null) - { - // pref optimization to avoid reading into a string builder - // if string is smaller than the buffer then return it directly - var length = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0); - - MovePosition(totalBytesRead + 1); - return new string(_charBuffer, 0, length); - } - // calculate the index of the end of the last full character in the buffer - var lastFullCharStop = GetLastFullCharStop(count - 1); - - var charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); - - if (builder == null) builder = new StringBuilder(MaxCharBytesSize * 2); - - builder.Append(_charBuffer, 0, charCount); - - if (lastFullCharStop < byteCount - 1) - { - offset = byteCount - lastFullCharStop - 1; - // copy left over multi byte characters to beginning of buffer for next iteration - Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset); - } - else - { - // reached end of string - if (count < MaxCharBytesSize) - { - MovePosition(totalBytesRead + 1); - return builder.ToString(); - } - - offset = 0; - } - } - } - - private string ReadLengthString() - { - var length = ReadInt32(); - - MovePosition(length); - - var s = GetString(length - 1); - _reader.ReadByte(); - - return s; - } - - private string GetString(int length) - { - if (length == 0) return string.Empty; - - EnsureBuffers(); - - StringBuilder builder = null; - - var totalBytesRead = 0; - - // used in case of left over multibyte characters in the buffer - var offset = 0; - do - { - var count = length - totalBytesRead > MaxCharBytesSize - offset - ? MaxCharBytesSize - offset - : length - totalBytesRead; - - var byteCount = _reader.Read(_byteBuffer, offset, count); - - if (byteCount == 0) throw new EndOfStreamException("Unable to read beyond the end of the stream."); - - totalBytesRead += byteCount; - - // Above, byteCount is how many bytes we read this time. - // Below, byteCount is how many bytes are in the _byteBuffer. - byteCount += offset; - - if (byteCount == length) - { - // pref optimization to avoid reading into a string builder - // first iteration and all bytes read then return string directly - var charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0); - return new string(_charBuffer, 0, charCount); - } - else - { - var lastFullCharStop = GetLastFullCharStop(byteCount - 1); - - if (builder == null) builder = new StringBuilder(length); - - var charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); - builder.Append(_charBuffer, 0, charCount); - - if (lastFullCharStop < byteCount - 1) - { - offset = byteCount - lastFullCharStop - 1; - // copy left over multi byte characters to beginning of buffer for next iteration - Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset); - } - else - offset = 0; - } - } while (totalBytesRead < length); - - return builder.ToString(); - } - - private int GetLastFullCharStop(int start) - { - var lookbackPos = start; - var bis = 0; - while (lookbackPos >= 0) - { - bis = BytesInSequence(_byteBuffer[lookbackPos]); - if (bis == 0) - lookbackPos--; - else if (bis == 1) - break; - else - { - lookbackPos--; - break; - } - } - if (bis == start - lookbackPos) - { - //Full character. - return start; - } - return lookbackPos; - } - - private int BytesInSequence(byte b) - { - if (b <= SeqRange1[1]) return 1; - - if (b >= SeqRange2[0] && b <= SeqRange2[1]) return 2; - - if (b >= SeqRange3[0] && b <= SeqRange3[1]) return 3; - - if (b >= SeqRange4[0] && b <= SeqRange4[1]) return 4; - - return 0; - } - - private void EnsureBuffers() - { - if (_byteBuffer == null) _byteBuffer = new byte[MaxCharBytesSize]; - if (_charBuffer == null) - { - var charBufferSize = Encoding.UTF8.GetMaxCharCount(MaxCharBytesSize); - _charBuffer = new char[charBufferSize]; - } - } - - private double ReadDouble() - { - MovePosition(8); - return _reader.ReadDouble(); - } - - private int ReadInt32() - { - MovePosition(4); - return _reader.ReadInt32(); - } - - private long ReadInt64() - { - MovePosition(8); - return _reader.ReadInt64(); - } - - private BsonType ReadType() - { - MovePosition(1); - return (BsonType)_reader.ReadSByte(); - } - - private void MovePosition(int count) => _currentContext.Position += count; - - private byte[] ReadBytes(int count) - { - MovePosition(count); - return _reader.ReadBytes(count); - } - - private enum BsonReaderState - { - Normal = 0, - ReferenceStart = 1, - ReferenceRef = 2, - ReferenceId = 3, - CodeWScopeStart = 4, - CodeWScopeCode = 5, - CodeWScopeScope = 6, - CodeWScopeScopeObject = 7, - CodeWScopeScopeEnd = 8 - } - - private class ContainerContext - { - public readonly BsonType Type; - - public ContainerContext(BsonType type) => Type = type; - - public int Length; - public int Position; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonToken.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonToken.cs deleted file mode 100644 index feae3b062..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonToken.cs +++ /dev/null @@ -1,146 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Collections; -using System.Collections.Generic; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - internal abstract class BsonToken - { - public abstract BsonType Type { get; } - public int CalculatedSize { get; set; } - public BsonToken Parent { get; set; } - } - - internal class BsonObject : BsonToken, IEnumerable - { - private readonly List _children = new(); - - public override BsonType Type => BsonType.Object; - - public void Add(string name, BsonToken token) - { - _children.Add(new BsonProperty { Name = new BsonString(name, false), Value = token }); - token.Parent = this; - } - - public IEnumerator GetEnumerator() => _children.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - internal class BsonArray : BsonToken, IEnumerable - { - private readonly List _children = new(); - - public override BsonType Type => BsonType.Array; - - public void Add(BsonToken token) - { - _children.Add(token); - token.Parent = this; - } - - public IEnumerator GetEnumerator() => _children.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - internal class BsonEmpty : BsonToken - { - public static readonly BsonToken Null = new BsonEmpty(BsonType.Null); - public static readonly BsonToken Undefined = new BsonEmpty(BsonType.Undefined); - - private BsonEmpty(BsonType type) => Type = type; - - public override BsonType Type { get; } - } - - internal class BsonValue : BsonToken - { - public BsonValue(object value, BsonType type) - { - Value = value; - Type = type; - } - - public override BsonType Type { get; } - - public object Value { get; } - } - - internal class BsonBoolean : BsonValue - { - public static readonly BsonBoolean False = new(false); - public static readonly BsonBoolean True = new(true); - - private BsonBoolean(bool value) - : base(value, BsonType.Boolean) { } - } - - internal class BsonString : BsonValue - { - public BsonString(object value, bool includeLength) - : base(value, BsonType.String) => - IncludeLength = includeLength; - - public int ByteCount { get; set; } - public bool IncludeLength { get; } - } - - internal class BsonBinary : BsonValue - { - public BsonBinary(byte[] value, BsonBinaryType binaryType) - : base(value, BsonType.Binary) => - BinaryType = binaryType; - - public BsonBinaryType BinaryType { get; set; } - } - - internal class BsonRegex : BsonToken - { - public BsonRegex(string pattern, string options) - { - Pattern = new BsonString(pattern, false); - Options = new BsonString(options, false); - } - - public BsonString Options { get; set; } - public BsonString Pattern { get; set; } - - public override BsonType Type => BsonType.Regex; - } - - internal class BsonProperty - { - public BsonString Name { get; set; } - public BsonToken Value { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonType.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonType.cs deleted file mode 100644 index 11cb8ad88..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonType.cs +++ /dev/null @@ -1,55 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - internal enum BsonType : sbyte - { - Number = 1, - String = 2, - Object = 3, - Array = 4, - Binary = 5, - Undefined = 6, - Oid = 7, - Boolean = 8, - Date = 9, - Null = 10, - Regex = 11, - Reference = 12, - Code = 13, - Symbol = 14, - CodeWScope = 15, - Integer = 16, - TimeStamp = 17, - Long = 18, - MinKey = -1, - MaxKey = 127 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonWriter.cs deleted file mode 100644 index aee9f44da..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Bson/BsonWriter.cs +++ /dev/null @@ -1,507 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Bson -{ - /// - /// Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data. - /// - [Obsolete( - "BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] - internal class BsonWriter : JsonWriter - { - private readonly BsonBinaryWriter _writer; - - private BsonToken _root; - private BsonToken _parent; - private string _propertyName; - - /// - /// Gets or sets the used when writing values to BSON. - /// When set to no conversion will occur. - /// - /// The used when writing values to BSON. - public DateTimeKind DateTimeKindHandling - { - get => _writer.DateTimeKindHandling; - set => _writer.DateTimeKindHandling = value; - } - - /// - /// Initializes a new instance of the class. - /// - /// The to write to. - public BsonWriter(Stream stream) - { - ValidationUtils.ArgumentNotNull(stream, nameof(stream)); - _writer = new BsonBinaryWriter(new BinaryWriter(stream)); - } - - /// - /// Initializes a new instance of the class. - /// - /// The to write to. - public BsonWriter(BinaryWriter writer) - { - ValidationUtils.ArgumentNotNull(writer, nameof(writer)); - _writer = new BsonBinaryWriter(writer); - } - - /// - /// Flushes whatever is in the buffer to the underlying and also flushes the underlying stream. - /// - public override void Flush() => _writer.Flush(); - - /// - /// Writes the end. - /// - /// The token. - protected override void WriteEnd(JsonToken token) - { - base.WriteEnd(token); - RemoveParent(); - - if (Top == 0) _writer.WriteToken(_root); - } - - /// - /// Writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - public override void WriteComment(string text) => throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null); - - /// - /// Writes the start of a constructor with the given name. - /// - /// The name of the constructor. - public override void WriteStartConstructor(string name) => - throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null); - - /// - /// Writes raw JSON. - /// - /// The raw JSON to write. - public override void WriteRaw(string json) => throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); - - /// - /// Writes raw JSON where a value is expected and updates the writer's state. - /// - /// The raw JSON to write. - public override void WriteRawValue(string json) => throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); - - /// - /// Writes the beginning of a JSON array. - /// - public override void WriteStartArray() - { - base.WriteStartArray(); - - AddParent(new BsonArray()); - } - - /// - /// Writes the beginning of a JSON object. - /// - public override void WriteStartObject() - { - base.WriteStartObject(); - - AddParent(new BsonObject()); - } - - /// - /// Writes the property name of a name/value pair on a JSON object. - /// - /// The name of the property. - public override void WritePropertyName(string name) - { - base.WritePropertyName(name); - - _propertyName = name; - } - - /// - /// Closes this writer. - /// If is set to true, the underlying is also closed. - /// If is set to true, the JSON is auto-completed. - /// - public override void Close() - { - base.Close(); - - if (CloseOutput) _writer?.Close(); - } - - private void AddParent(BsonToken container) - { - AddToken(container); - _parent = container; - } - - private void RemoveParent() => _parent = _parent.Parent; - - private void AddValue(object value, BsonType type) => AddToken(new BsonValue(value, type)); - - internal void AddToken(BsonToken token) - { - if (_parent != null) - { - if (_parent is BsonObject bo) - { - bo.Add(_propertyName, token); - _propertyName = null; - } - else - ((BsonArray)_parent).Add(token); - } - else - { - if (token.Type != BsonType.Object && token.Type != BsonType.Array) - throw JsonWriterException.Create(this, - "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), - null); - - _parent = token; - _root = token; - } - } - - #region WriteValue methods - - /// - /// Writes a value. - /// An error will raised if the value cannot be written as a single JSON token. - /// - /// The value to write. - public override void WriteValue(object value) - { -#if HAVE_BIG_INTEGER - if (value is BigInteger i) - { - SetWriteState(JsonToken.Integer, null); - AddToken(new BsonBinary(i.ToByteArray(), BsonBinaryType.Binary)); - } - else -#endif - { - base.WriteValue(value); - } - } - - /// - /// Writes a null value. - /// - public override void WriteNull() - { - base.WriteNull(); - AddToken(BsonEmpty.Null); - } - - /// - /// Writes an undefined value. - /// - public override void WriteUndefined() - { - base.WriteUndefined(); - AddToken(BsonEmpty.Undefined); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(string value) - { - base.WriteValue(value); - AddToken(value == null ? BsonEmpty.Null : new BsonString(value, true)); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(int value) - { - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(uint value) - { - if (value > int.MaxValue) - throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", - null); - - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(long value) - { - base.WriteValue(value); - AddValue(value, BsonType.Long); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ulong value) - { - if (value > long.MaxValue) - throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", - null); - - base.WriteValue(value); - AddValue(value, BsonType.Long); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(float value) - { - base.WriteValue(value); - AddValue(value, BsonType.Number); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(double value) - { - base.WriteValue(value); - AddValue(value, BsonType.Number); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(bool value) - { - base.WriteValue(value); - AddToken(value ? BsonBoolean.True : BsonBoolean.False); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(short value) - { - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ushort value) - { - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(char value) - { - base.WriteValue(value); - string s = null; -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - s = value.ToString(CultureInfo.InvariantCulture); -#else - s = value.ToString(); -#endif - AddToken(new BsonString(s, true)); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(byte value) - { - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(sbyte value) - { - base.WriteValue(value); - AddValue(value, BsonType.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(decimal value) - { - base.WriteValue(value); - AddValue(value, BsonType.Number); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTime value) - { - base.WriteValue(value); - value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); - AddValue(value, BsonType.Date); - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTimeOffset value) - { - base.WriteValue(value); - AddValue(value, BsonType.Date); - } -#endif - - /// - /// Writes a [] value. - /// - /// The [] value to write. - public override void WriteValue(byte[] value) - { - if (value == null) - { - WriteNull(); - return; - } - - base.WriteValue(value); - AddToken(new BsonBinary(value, BsonBinaryType.Binary)); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Guid value) - { - base.WriteValue(value); - AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid)); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(TimeSpan value) - { - base.WriteValue(value); - AddToken(new BsonString(value.ToString(), true)); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Uri value) - { - if (value == null) - { - WriteNull(); - return; - } - - base.WriteValue(value); - AddToken(new BsonString(value.ToString(), true)); - } - - #endregion - - /// - /// Writes a [] value that represents a BSON object id. - /// - /// The Object ID value to write. - public void WriteObjectId(byte[] value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - if (value.Length != 12) throw JsonWriterException.Create(this, "An object id must be 12 bytes", null); - - // hack to update the writer state - SetWriteState(JsonToken.Undefined, null); - AddValue(value, BsonType.Oid); - } - - /// - /// Writes a BSON regex. - /// - /// The regex pattern. - /// The regex options. - public void WriteRegex(string pattern, string options) - { - ValidationUtils.ArgumentNotNull(pattern, nameof(pattern)); - - // hack to update the writer state - SetWriteState(JsonToken.Undefined, null); - AddToken(new BsonRegex(pattern, options)); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ConstructorHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/ConstructorHandling.cs deleted file mode 100644 index 3e74ee497..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ConstructorHandling.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how constructors are used when initializing objects during deserialization by the - /// . - /// - internal enum ConstructorHandling - { - /// - /// First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the - /// non-public default constructor. - /// - Default = 0, - - /// - /// Json.NET will use a non-public default constructor before falling back to a parameterized constructor. - /// - AllowNonPublicDefaultConstructor = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BinaryConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BinaryConverter.cs deleted file mode 100644 index 70f605932..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BinaryConverter.cs +++ /dev/null @@ -1,214 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_LINQ || HAVE_ADO_NET -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using System.Collections.Generic; -#if HAVE_ADO_NET -using System.Data.SqlTypes; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a binary value to and from a base 64 string value. - /// - internal class BinaryConverter : JsonConverter - { -#if HAVE_LINQ - private const string BinaryTypeName = "System.Data.Linq.Binary"; - private const string BinaryToArrayName = "ToArray"; - private ReflectionObject? _reflectionObject; -#endif - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - byte[] data = GetByteArray(value); - - writer.WriteValue(data); - } - - private byte[] GetByteArray(object value) - { -#if HAVE_LINQ - if (value.GetType().FullName == BinaryTypeName) - { - EnsureReflectionObject(value.GetType()); - MiscellaneousUtils.Assert(_reflectionObject != null); - - return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName)!; - } -#endif -#if HAVE_ADO_NET - if (value is SqlBinary binary) - { - return binary.Value; - } -#endif - - throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType())); - } - -#if HAVE_LINQ - private void EnsureReflectionObject(Type t) - { - if (_reflectionObject == null) - { - _reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new[] { typeof(byte[]) }), BinaryToArrayName); - } - } -#endif - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - if (!ReflectionUtils.IsNullable(objectType)) - { - throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - - return null; - } - - byte[] data; - - if (reader.TokenType == JsonToken.StartArray) - { - data = ReadByteArray(reader); - } - else if (reader.TokenType == JsonToken.String) - { - // current token is already at base64 string - // unable to call ReadAsBytes so do it the old fashion way - string encodedData = reader.Value!.ToString(); - data = Convert.FromBase64String(encodedData); - } - else - { - throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - -#if HAVE_LINQ - if (t.FullName == BinaryTypeName) - { - EnsureReflectionObject(t); - MiscellaneousUtils.Assert(_reflectionObject != null); - - return _reflectionObject.Creator!(data); - } -#endif - -#if HAVE_ADO_NET - if (t == typeof(SqlBinary)) - { - return new SqlBinary(data); - } -#endif - - throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - - private byte[] ReadByteArray(JsonReader reader) - { - List byteList = new List(); - - while (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.Integer: - byteList.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture)); - break; - case JsonToken.EndArray: - return byteList.ToArray(); - case JsonToken.Comment: - // skip - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } - - throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes."); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { -#if HAVE_LINQ - if (objectType.FullName == BinaryTypeName) - { - return true; - } -#endif -#if HAVE_ADO_NET - if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?)) - { - return true; - } -#endif - - return false; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs deleted file mode 100644 index 6332da7ed..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs +++ /dev/null @@ -1,87 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Bson; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from JSON and BSON. - /// - [Obsolete( - "BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] - internal class BsonObjectIdConverter : JsonConverter - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - var objectId = (BsonObjectId)value; - - if (writer is BsonWriter bsonWriter) - bsonWriter.WriteObjectId(objectId.Value); - else - writer.WriteValue(objectId.Value); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType != JsonToken.Bytes) - throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - - var value = (byte[])reader.Value; - - return new BsonObjectId(value); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) => objectType == typeof(BsonObjectId); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/CustomCreationConverter.cs deleted file mode 100644 index c1fbd0164..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/CustomCreationConverter.cs +++ /dev/null @@ -1,91 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Creates a custom object. - /// - /// The object type to convert. - internal abstract class CustomCreationConverter : JsonConverter - { - /// - /// Creates an object which will then be populated by the serializer. - /// - /// Type of the object. - /// The created object. - public abstract T Create(Type objectType); - - /// - /// Gets a value indicating whether this can write JSON. - /// - /// - /// true if this can write JSON; otherwise, false. - /// - public override bool CanWrite => false; - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotSupportedException("CustomCreationConverter should only be used while deserializing."); - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) return null; - - var value = Create(objectType); - if (value == null) throw new JsonSerializationException("No object created."); - - serializer.Populate(reader, value); - return value; - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) => typeof(T).IsAssignableFrom(objectType); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataSetConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataSetConverter.cs deleted file mode 100644 index 7c0821e40..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataSetConverter.cs +++ /dev/null @@ -1,128 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ADO_NET -using System; -using System.Data; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from JSON. - /// - internal class DataSetConverter : JsonConverter - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - DataSet dataSet = (DataSet)value; - DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; - - DataTableConverter converter = new DataTableConverter(); - - writer.WriteStartObject(); - - foreach (DataTable table in dataSet.Tables) - { - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(table.TableName) : table.TableName); - - converter.WriteJson(writer, table, serializer); - } - - writer.WriteEndObject(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - return null; - } - - // handle typed datasets - DataSet ds = (objectType == typeof(DataSet)) - ? new DataSet() - : (DataSet)Activator.CreateInstance(objectType); - - DataTableConverter converter = new DataTableConverter(); - - reader.ReadAndAssert(); - - while (reader.TokenType == JsonToken.PropertyName) - { - DataTable dt = ds.Tables[(string)reader.Value!]; - bool exists = (dt != null); - - dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer)!; - - if (!exists) - { - ds.Tables.Add(dt); - } - - reader.ReadAndAssert(); - } - - return ds; - } - - /// - /// Determines whether this instance can convert the specified value type. - /// - /// Type of the value. - /// - /// true if this instance can convert the specified value type; otherwise, false. - /// - public override bool CanConvert(Type valueType) - { - return typeof(DataSet).IsAssignableFrom(valueType); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataTableConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataTableConverter.cs deleted file mode 100644 index 0cb9ab8f8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DataTableConverter.cs +++ /dev/null @@ -1,257 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ADO_NET -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using System; -using System.Data; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from JSON. - /// - internal class DataTableConverter : JsonConverter - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - DataTable table = (DataTable)value; - DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; - - writer.WriteStartArray(); - - foreach (DataRow row in table.Rows) - { - writer.WriteStartObject(); - foreach (DataColumn column in row.Table.Columns) - { - object columnValue = row[column]; - - if (serializer.NullValueHandling == NullValueHandling.Ignore && (columnValue == null || columnValue == DBNull.Value)) - { - continue; - } - - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName); - serializer.Serialize(writer, columnValue); - } - writer.WriteEndObject(); - } - - writer.WriteEndArray(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - return null; - } - - if (!(existingValue is DataTable dt)) - { - // handle typed datasets - dt = (objectType == typeof(DataTable)) - ? new DataTable() - : (DataTable)Activator.CreateInstance(objectType); - } - - // DataTable is inside a DataSet - // populate the name from the property name - if (reader.TokenType == JsonToken.PropertyName) - { - dt.TableName = (string)reader.Value!; - - reader.ReadAndAssert(); - - if (reader.TokenType == JsonToken.Null) - { - return dt; - } - } - - if (reader.TokenType != JsonToken.StartArray) - { - throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - reader.ReadAndAssert(); - - while (reader.TokenType != JsonToken.EndArray) - { - CreateRow(reader, dt, serializer); - - reader.ReadAndAssert(); - } - - return dt; - } - - private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer serializer) - { - DataRow dr = dt.NewRow(); - reader.ReadAndAssert(); - - while (reader.TokenType == JsonToken.PropertyName) - { - string columnName = (string)reader.Value!; - - reader.ReadAndAssert(); - - DataColumn column = dt.Columns[columnName]; - if (column == null) - { - Type columnType = GetColumnDataType(reader); - column = new DataColumn(columnName, columnType); - dt.Columns.Add(column); - } - - if (column.DataType == typeof(DataTable)) - { - if (reader.TokenType == JsonToken.StartArray) - { - reader.ReadAndAssert(); - } - - DataTable nestedDt = new DataTable(); - - while (reader.TokenType != JsonToken.EndArray) - { - CreateRow(reader, nestedDt, serializer); - - reader.ReadAndAssert(); - } - - dr[columnName] = nestedDt; - } - else if (column.DataType.IsArray && column.DataType != typeof(byte[])) - { - if (reader.TokenType == JsonToken.StartArray) - { - reader.ReadAndAssert(); - } - - List o = new List(); - - while (reader.TokenType != JsonToken.EndArray) - { - o.Add(reader.Value); - reader.ReadAndAssert(); - } - - Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count); - ((IList)o).CopyTo(destinationArray, 0); - - dr[columnName] = destinationArray; - } - else - { - object columnValue = (reader.Value != null) - ? serializer.Deserialize(reader, column.DataType) ?? DBNull.Value - : DBNull.Value; - - dr[columnName] = columnValue; - } - - reader.ReadAndAssert(); - } - - dr.EndEdit(); - dt.Rows.Add(dr); - } - - private static Type GetColumnDataType(JsonReader reader) - { - JsonToken tokenType = reader.TokenType; - - switch (tokenType) - { - case JsonToken.Integer: - case JsonToken.Boolean: - case JsonToken.Float: - case JsonToken.String: - case JsonToken.Date: - case JsonToken.Bytes: - return reader.ValueType!; - case JsonToken.Null: - case JsonToken.Undefined: - case JsonToken.EndArray: - return typeof(string); - case JsonToken.StartArray: - reader.ReadAndAssert(); - if (reader.TokenType == JsonToken.StartObject) - { - return typeof(DataTable); // nested datatable - } - - Type arrayType = GetColumnDataType(reader); - return arrayType.MakeArrayType(); - default: - throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); - } - } - - /// - /// Determines whether this instance can convert the specified value type. - /// - /// Type of the value. - /// - /// true if this instance can convert the specified value type; otherwise, false. - /// - public override bool CanConvert(Type valueType) - { - return typeof(DataTable).IsAssignableFrom(valueType); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DateTimeConverterBase.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DateTimeConverterBase.cs deleted file mode 100644 index dad582671..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DateTimeConverterBase.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Provides a base class for converting a to and from JSON. - /// - internal abstract class DateTimeConverterBase : JsonConverter - { - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - if (objectType == typeof(DateTime) || objectType == typeof(DateTime?)) return true; -#if HAVE_DATE_TIME_OFFSET - if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?)) - { - return true; - } -#endif - - return false; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs deleted file mode 100644 index 52c3155a3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs +++ /dev/null @@ -1,301 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_FSHARP_TYPES -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using System; -using System.Collections; -using System.Collections.Generic; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a F# discriminated union type to and from JSON. - /// - internal class DiscriminatedUnionConverter : JsonConverter - { - #region UnionDefinition - internal class Union - { - public readonly FSharpFunction TagReader; - public readonly List Cases; - - public Union(FSharpFunction tagReader, List cases) - { - TagReader = tagReader; - Cases = cases; - } - } - - internal class UnionCase - { - public readonly int Tag; - public readonly string Name; - public readonly PropertyInfo[] Fields; - public readonly FSharpFunction FieldReader; - public readonly FSharpFunction Constructor; - - public UnionCase(int tag, string name, PropertyInfo[] fields, FSharpFunction fieldReader, FSharpFunction constructor) - { - Tag = tag; - Name = name; - Fields = fields; - FieldReader = fieldReader; - Constructor = constructor; - } - } - #endregion - - private const string CasePropertyName = "Case"; - private const string FieldsPropertyName = "Fields"; - - private static readonly ThreadSafeStore UnionCache = new ThreadSafeStore(CreateUnion); - private static readonly ThreadSafeStore UnionTypeLookupCache = new ThreadSafeStore(CreateUnionTypeLookup); - - private static Type CreateUnionTypeLookup(Type t) - { - // this lookup is because cases with fields are derived from union type - // need to get declaring type to avoid duplicate Unions in cache - - // hacky but I can't find an API to get the declaring type without GetUnionCases - object[] cases = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null)!; - - object caseInfo = cases.First(); - - Type unionType = (Type)FSharpUtils.Instance.GetUnionCaseInfoDeclaringType(caseInfo)!; - return unionType; - } - - private static Union CreateUnion(Type t) - { - Union u = new Union((FSharpFunction)FSharpUtils.Instance.PreComputeUnionTagReader(null, t, null), new List()); - - object[] cases = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null)!; - - foreach (object unionCaseInfo in cases) - { - UnionCase unionCase = new UnionCase( - (int)FSharpUtils.Instance.GetUnionCaseInfoTag(unionCaseInfo), - (string)FSharpUtils.Instance.GetUnionCaseInfoName(unionCaseInfo), - (PropertyInfo[])FSharpUtils.Instance.GetUnionCaseInfoFields(unionCaseInfo)!, - (FSharpFunction)FSharpUtils.Instance.PreComputeUnionReader(null, unionCaseInfo, null), - (FSharpFunction)FSharpUtils.Instance.PreComputeUnionConstructor(null, unionCaseInfo, null)); - - u.Cases.Add(unionCase); - } - - return u; - } - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; - - Type unionType = UnionTypeLookupCache.Get(value.GetType()); - Union union = UnionCache.Get(unionType); - - int tag = (int)union.TagReader.Invoke(value); - UnionCase caseInfo = union.Cases.Single(c => c.Tag == tag); - - writer.WriteStartObject(); - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName); - writer.WriteValue(caseInfo.Name); - if (caseInfo.Fields != null && caseInfo.Fields.Length > 0) - { - object[] fields = (object[])caseInfo.FieldReader.Invoke(value)!; - - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName); - writer.WriteStartArray(); - foreach (object field in fields) - { - serializer.Serialize(writer, field); - } - writer.WriteEndArray(); - } - writer.WriteEndObject(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - return null; - } - - UnionCase? caseInfo = null; - string? caseName = null; - JArray? fields = null; - - // start object - reader.ReadAndAssert(); - - while (reader.TokenType == JsonToken.PropertyName) - { - string propertyName = reader.Value!.ToString(); - if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase)) - { - reader.ReadAndAssert(); - - Union union = UnionCache.Get(objectType); - - caseName = reader.Value!.ToString(); - - caseInfo = union.Cases.SingleOrDefault(c => c.Name == caseName); - - if (caseInfo == null) - { - throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); - } - } - else if (string.Equals(propertyName, FieldsPropertyName, StringComparison.OrdinalIgnoreCase)) - { - reader.ReadAndAssert(); - if (reader.TokenType != JsonToken.StartArray) - { - throw JsonSerializationException.Create(reader, "Union fields must been an array."); - } - - fields = (JArray)JToken.ReadFrom(reader); - } - else - { - throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, propertyName)); - } - - reader.ReadAndAssert(); - } - - if (caseInfo == null) - { - throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName)); - } - - object?[] typedFieldValues = new object?[caseInfo.Fields.Length]; - - if (caseInfo.Fields.Length > 0 && fields == null) - { - throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, FieldsPropertyName)); - } - - if (fields != null) - { - if (caseInfo.Fields.Length != fields.Count) - { - throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties defined by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); - } - - for (int i = 0; i < fields.Count; i++) - { - JToken t = fields[i]; - PropertyInfo fieldProperty = caseInfo.Fields[i]; - - typedFieldValues[i] = t.ToObject(fieldProperty.PropertyType, serializer); - } - } - - object[] args = { typedFieldValues }; - - return caseInfo.Constructor.Invoke(args); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - if (typeof(IEnumerable).IsAssignableFrom(objectType)) - { - return false; - } - - // all fsharp objects have CompilationMappingAttribute - // get the fsharp assembly from the attribute and initialize latebound methods - object[] attributes; -#if HAVE_FULL_REFLECTION - attributes = objectType.GetCustomAttributes(true); -#else - attributes = objectType.GetTypeInfo().GetCustomAttributes(true).ToArray(); -#endif - - bool isFSharpType = false; - foreach (object attribute in attributes) - { - Type attributeType = attribute.GetType(); - if (attributeType.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute") - { - FSharpUtils.EnsureInitialized(attributeType.Assembly()); - - isFSharpType = true; - break; - } - } - - if (!isFSharpType) - { - return false; - } - - return (bool)FSharpUtils.Instance.IsUnion(null, objectType, null); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs deleted file mode 100644 index ecd7a0ee7..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs +++ /dev/null @@ -1,167 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ENTITY_FRAMEWORK -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts an Entity Framework to and from JSON. - /// - internal class EntityKeyMemberConverter : JsonConverter - { - private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember"; - - private const string KeyPropertyName = "Key"; - private const string TypePropertyName = "Type"; - private const string ValuePropertyName = "Value"; - - private static ReflectionObject? _reflectionObject; - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - EnsureReflectionObject(value.GetType()); - MiscellaneousUtils.Assert(_reflectionObject != null); - - DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; - - string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName)!; - object? keyValue = _reflectionObject.GetValue(value, ValuePropertyName); - - Type? keyValueType = keyValue?.GetType(); - - writer.WriteStartObject(); - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName); - writer.WriteValue(keyName); - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(TypePropertyName) : TypePropertyName); - writer.WriteValue(keyValueType?.FullName); - - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValuePropertyName) : ValuePropertyName); - - if (keyValueType != null) - { - if (JsonSerializerInternalWriter.TryConvertToString(keyValue!, keyValueType, out string? valueJson)) - { - writer.WriteValue(valueJson); - } - else - { - writer.WriteValue(keyValue); - } - } - else - { - writer.WriteNull(); - } - - writer.WriteEndObject(); - } - - private static void ReadAndAssertProperty(JsonReader reader, string propertyName) - { - reader.ReadAndAssert(); - - if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value?.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) - { - throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName)); - } - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - EnsureReflectionObject(objectType); - MiscellaneousUtils.Assert(_reflectionObject != null); - - object entityKeyMember = _reflectionObject.Creator!(); - - ReadAndAssertProperty(reader, KeyPropertyName); - reader.ReadAndAssert(); - _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value?.ToString()); - - ReadAndAssertProperty(reader, TypePropertyName); - reader.ReadAndAssert(); - string? type = reader.Value?.ToString(); - - Type t = Type.GetType(type); - - ReadAndAssertProperty(reader, ValuePropertyName); - reader.ReadAndAssert(); - _reflectionObject.SetValue(entityKeyMember, ValuePropertyName, serializer.Deserialize(reader, t)); - - reader.ReadAndAssert(); - - return entityKeyMember; - } - - private static void EnsureReflectionObject(Type objectType) - { - if (_reflectionObject == null) - { - _reflectionObject = ReflectionObject.Create(objectType, KeyPropertyName, ValuePropertyName); - } - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - return objectType.AssignableToTypeName(EntityKeyMemberFullTypeName, false); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs deleted file mode 100644 index 3bb0a35dc..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs +++ /dev/null @@ -1,165 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts an to and from JSON. - /// - internal class ExpandoObjectConverter : JsonConverter - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - // can write is set to false - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - return ReadValue(reader); - } - - private object? ReadValue(JsonReader reader) - { - if (!reader.MoveToContent()) - { - throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); - } - - switch (reader.TokenType) - { - case JsonToken.StartObject: - return ReadObject(reader); - case JsonToken.StartArray: - return ReadList(reader); - default: - if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) - { - return reader.Value; - } - - throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } - - private object ReadList(JsonReader reader) - { - IList list = new List(); - - while (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.Comment: - break; - default: - object? v = ReadValue(reader); - - list.Add(v); - break; - case JsonToken.EndArray: - return list; - } - } - - throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); - } - - private object ReadObject(JsonReader reader) - { - IDictionary expandoObject = new ExpandoObject(); - - while (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - string propertyName = reader.Value!.ToString(); - - if (!reader.Read()) - { - throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); - } - - object? v = ReadValue(reader); - - expandoObject[propertyName] = v; - break; - case JsonToken.Comment: - break; - case JsonToken.EndObject: - return expandoObject; - } - } - - throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(ExpandoObject)); - } - - /// - /// Gets a value indicating whether this can write JSON. - /// - /// - /// true if this can write JSON; otherwise, false. - /// - public override bool CanWrite => false; - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs deleted file mode 100644 index 1d488b6a5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs +++ /dev/null @@ -1,180 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from the ISO 8601 date format (e.g. "2008-04-12T12:53Z"). - /// - internal class IsoDateTimeConverter : DateTimeConverterBase - { - private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; - private CultureInfo? _culture; - private string? _dateTimeFormat; - - /// - /// Gets or sets the culture used when converting a date to and from JSON. - /// - /// The culture used when converting a date to and from JSON. - public CultureInfo Culture - { - get => _culture ?? CultureInfo.CurrentCulture; - set => _culture = value; - } - - /// - /// Gets or sets the date time format used when converting a date to and from JSON. - /// - /// The date time format used when converting a date to and from JSON. - public string? DateTimeFormat - { - get => _dateTimeFormat ?? string.Empty; - set => _dateTimeFormat = StringUtils.IsNullOrEmpty(value) ? null : value; - } - - /// - /// Gets or sets the date time styles used when converting a date to and from JSON. - /// - /// The date time styles used when converting a date to and from JSON. - public DateTimeStyles DateTimeStyles { get; set; } = DateTimeStyles.RoundtripKind; - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - string text; - - if (value is DateTime dateTime) - { - if ((DateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal - || (DateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) - dateTime = dateTime.ToUniversalTime(); - - text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); - } -#if HAVE_DATE_TIME_OFFSET - else if (value is DateTimeOffset dateTimeOffset) - { - if ((DateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal - || (DateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) - { - dateTimeOffset = dateTimeOffset.ToUniversalTime(); - } - - text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); - } -#endif - else - throw new JsonSerializationException( - "Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, - ReflectionUtils.GetObjectType(value)!)); - - writer.WriteValue(text); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var nullable = ReflectionUtils.IsNullableType(objectType); - if (reader.TokenType == JsonToken.Null) - { - if (!nullable) - throw JsonSerializationException.Create(reader, - "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - - return null; - } - -#if HAVE_DATE_TIME_OFFSET - Type t = (nullable) - ? Nullable.GetUnderlyingType(objectType) - : objectType; -#endif - - if (reader.TokenType == JsonToken.Date) - { -#if HAVE_DATE_TIME_OFFSET - if (t == typeof(DateTimeOffset)) - { - return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value!); - } - - // converter is expected to return a DateTime - if (reader.Value is DateTimeOffset offset) - { - return offset.DateTime; - } -#endif - - return reader.Value; - } - - if (reader.TokenType != JsonToken.String) - throw JsonSerializationException.Create(reader, - "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - - var dateText = reader.Value?.ToString(); - - if (StringUtils.IsNullOrEmpty(dateText) && nullable) return null; - -#if HAVE_DATE_TIME_OFFSET - if (t == typeof(DateTimeOffset)) - { - if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) - { - return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, DateTimeStyles); - } - else - { - return DateTimeOffset.Parse(dateText, Culture, DateTimeStyles); - } - } -#endif - - if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) - return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, DateTimeStyles); - - return DateTime.Parse(dateText, Culture, DateTimeStyles); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs deleted file mode 100644 index 649db195a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs +++ /dev/null @@ -1,109 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from a JavaScript Date constructor (e.g. new Date(52231943)). - /// - internal class JavaScriptDateTimeConverter : DateTimeConverterBase - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - long ticks; - - if (value is DateTime dateTime) - { - var utcDateTime = dateTime.ToUniversalTime(); - ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTime); - } -#if HAVE_DATE_TIME_OFFSET - else if (value is DateTimeOffset dateTimeOffset) - { - DateTimeOffset utcDateTimeOffset = dateTimeOffset.ToUniversalTime(); - ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTimeOffset.UtcDateTime); - } -#endif - else - throw new JsonSerializationException("Expected date object value."); - - writer.WriteStartConstructor("Date"); - writer.WriteValue(ticks); - writer.WriteEndConstructor(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing property value of the JSON that is being converted. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - if (!ReflectionUtils.IsNullable(objectType)) - throw JsonSerializationException.Create(reader, - "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - - return null; - } - - if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) - throw JsonSerializationException.Create(reader, - "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, - reader.Value)); - - if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out var d, out var errorMessage)) - throw JsonSerializationException.Create(reader, errorMessage); - -#if HAVE_DATE_TIME_OFFSET - Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - if (t == typeof(DateTimeOffset)) - { - return new DateTimeOffset(d); - } -#endif - return d; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/KeyValuePairConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/KeyValuePairConverter.cs deleted file mode 100644 index 8103911d2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/KeyValuePairConverter.cs +++ /dev/null @@ -1,154 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from JSON. - /// - internal class KeyValuePairConverter : JsonConverter - { - private const string KeyName = "Key"; - private const string ValueName = "Value"; - - private static readonly ThreadSafeStore ReflectionObjectPerType = new(InitializeReflectionObject); - - private static ReflectionObject InitializeReflectionObject(Type t) - { - IList genericArguments = t.GetGenericArguments(); - var keyType = genericArguments[0]; - var valueType = genericArguments[1]; - - return ReflectionObject.Create(t, t.GetConstructor(new[] { keyType, valueType }), KeyName, ValueName); - } - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - var reflectionObject = ReflectionObjectPerType.Get(value.GetType()); - - var resolver = serializer.ContractResolver as DefaultContractResolver; - - writer.WriteStartObject(); - writer.WritePropertyName(resolver != null ? resolver.GetResolvedPropertyName(KeyName) : KeyName); - serializer.Serialize(writer, reflectionObject.GetValue(value, KeyName), reflectionObject.GetType(KeyName)); - writer.WritePropertyName(resolver != null ? resolver.GetResolvedPropertyName(ValueName) : ValueName); - serializer.Serialize(writer, reflectionObject.GetValue(value, ValueName), reflectionObject.GetType(ValueName)); - writer.WriteEndObject(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - if (!ReflectionUtils.IsNullableType(objectType)) - throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair."); - - return null; - } - - object? key = null; - object? value = null; - - reader.ReadAndAssert(); - - var t = ReflectionUtils.IsNullableType(objectType) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - - var reflectionObject = ReflectionObjectPerType.Get(t); - var keyContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType(KeyName)); - var valueContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType(ValueName)); - - while (reader.TokenType == JsonToken.PropertyName) - { - var propertyName = reader.Value!.ToString(); - if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase)) - { - reader.ReadForTypeAndAssert(keyContract, false); - - key = serializer.Deserialize(reader, keyContract.UnderlyingType); - } - else if (string.Equals(propertyName, ValueName, StringComparison.OrdinalIgnoreCase)) - { - reader.ReadForTypeAndAssert(valueContract, false); - - value = serializer.Deserialize(reader, valueContract.UnderlyingType); - } - else - reader.Skip(); - - reader.ReadAndAssert(); - } - - return reflectionObject.Creator!(key, value); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - var t = ReflectionUtils.IsNullableType(objectType) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - - if (t.IsValueType() && t.IsGenericType()) return t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>); - - return false; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/StringEnumConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/StringEnumConverter.cs deleted file mode 100644 index 5c57a6c36..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ /dev/null @@ -1,276 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ - -#else - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts an to and from its name string value. - /// - internal class StringEnumConverter : JsonConverter - { - /// - /// Initializes a new instance of the class. - /// - public StringEnumConverter() { } - - /// - /// Initializes a new instance of the class. - /// - /// true if the written enum text will be camel case; otherwise, false. - [Obsolete("StringEnumConverter(bool) is obsolete. Create a converter with StringEnumConverter(NamingStrategy, bool) instead.")] - public StringEnumConverter(bool camelCaseText) - { - if (camelCaseText) NamingStrategy = new CamelCaseNamingStrategy(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The naming strategy used to resolve how enum text is written. - /// - /// true if integers are allowed when serializing and deserializing; otherwise, - /// false. - /// - public StringEnumConverter(NamingStrategy namingStrategy, bool allowIntegerValues = true) - { - NamingStrategy = namingStrategy; - AllowIntegerValues = allowIntegerValues; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The of the - /// used to write enum text. - /// - public StringEnumConverter(Type namingStrategyType) - { - ValidationUtils.ArgumentNotNull(namingStrategyType, nameof(namingStrategyType)); - - NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, null); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The of the - /// used to write enum text. - /// - /// - /// The parameter list to use when constructing the described - /// by . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the - /// that exactly matches the number, - /// order, and type of these parameters. - /// - public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters) - { - ValidationUtils.ArgumentNotNull(namingStrategyType, nameof(namingStrategyType)); - - NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The of the - /// used to write enum text. - /// - /// - /// The parameter list to use when constructing the described - /// by . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the - /// that exactly matches the number, - /// order, and type of these parameters. - /// - /// - /// true if integers are allowed when serializing and deserializing; otherwise, - /// false. - /// - public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters, bool allowIntegerValues) - { - ValidationUtils.ArgumentNotNull(namingStrategyType, nameof(namingStrategyType)); - - NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); - AllowIntegerValues = allowIntegerValues; - } - - /// - /// Gets or sets a value indicating whether integer values are allowed when serializing and deserializing. - /// The default value is true. - /// - /// true if integers are allowed when serializing and deserializing; otherwise, false. - public bool AllowIntegerValues { get; set; } = true; - - /// - /// Gets or sets a value indicating whether the written enum text should be camel case. - /// The default value is false. - /// - /// true if the written enum text will be camel case; otherwise, false. - [Obsolete("StringEnumConverter.CamelCaseText is obsolete. Set StringEnumConverter.NamingStrategy with CamelCaseNamingStrategy instead.")] - public bool CamelCaseText - { - get => NamingStrategy is CamelCaseNamingStrategy ? true : false; - set - { - if (value) - { - if (NamingStrategy is CamelCaseNamingStrategy) return; - - NamingStrategy = new CamelCaseNamingStrategy(); - } - else - { - if (!(NamingStrategy is CamelCaseNamingStrategy)) return; - - NamingStrategy = null; - } - } - } - - /// - /// Gets or sets the naming strategy used to resolve how enum text is written. - /// - /// The naming strategy used to resolve how enum text is written. - public NamingStrategy? NamingStrategy { get; set; } - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - var e = (Enum)value; - - if (!EnumUtils.TryToString(e.GetType(), value, NamingStrategy, out var enumName)) - { - if (!AllowIntegerValues) - throw JsonSerializationException.Create(null, writer.ContainerPath, - "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, e.ToString("D")), null); - - // enum value has no name so write number - writer.WriteValue(value); - } - else - writer.WriteValue(enumName); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - if (!ReflectionUtils.IsNullableType(objectType)) - throw JsonSerializationException.Create(reader, - "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - - return null; - } - - var isNullable = ReflectionUtils.IsNullableType(objectType); - var t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; - - try - { - if (reader.TokenType == JsonToken.String) - { - var enumText = reader.Value?.ToString(); - - if (StringUtils.IsNullOrEmpty(enumText) && isNullable) return null; - - return EnumUtils.ParseEnum(t, NamingStrategy, enumText!, !AllowIntegerValues); - } - - if (reader.TokenType == JsonToken.Integer) - { - if (!AllowIntegerValues) - throw JsonSerializationException.Create(reader, - "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value)); - - return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, t); - } - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(reader.Value), - objectType), ex); - } - - // we don't actually expect to get here. - throw JsonSerializationException.Create(reader, - "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - var t = ReflectionUtils.IsNullableType(objectType) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - - return t.IsEnum(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs deleted file mode 100644 index 805c2ba01..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs +++ /dev/null @@ -1,123 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from Unix epoch time - /// - internal class UnixDateTimeConverter : DateTimeConverterBase - { - internal static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - long seconds; - - if (value is DateTime dateTime) - seconds = (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds; -#if HAVE_DATE_TIME_OFFSET - else if (value is DateTimeOffset dateTimeOffset) - { - seconds = (long)(dateTimeOffset.ToUniversalTime() - UnixEpoch).TotalSeconds; - } -#endif - else - throw new JsonSerializationException("Expected date object value."); - - if (seconds < 0) - throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970."); - - writer.WriteValue(seconds); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing property value of the JSON that is being converted. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var nullable = ReflectionUtils.IsNullable(objectType); - if (reader.TokenType == JsonToken.Null) - { - if (!nullable) - throw JsonSerializationException.Create(reader, - "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - - return null; - } - - long seconds; - - if (reader.TokenType == JsonToken.Integer) - seconds = (long)reader.Value!; - else if (reader.TokenType == JsonToken.String) - { - if (!long.TryParse((string)reader.Value!, out seconds)) - throw JsonSerializationException.Create(reader, - "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - else - throw JsonSerializationException.Create(reader, - "Unexpected token parsing date. Expected Integer or String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - - if (seconds >= 0) - { - var d = UnixEpoch.AddSeconds(seconds); - -#if HAVE_DATE_TIME_OFFSET - Type t = (nullable) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - if (t == typeof(DateTimeOffset)) - { - return new DateTimeOffset(d, TimeSpan.Zero); - } -#endif - return d; - } - throw JsonSerializationException.Create(reader, - "Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970 to {0}.".FormatWith(CultureInfo.InvariantCulture, - objectType)); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/VersionConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/VersionConverter.cs deleted file mode 100644 index 9e79f2a39..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/VersionConverter.cs +++ /dev/null @@ -1,96 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - /// - /// Converts a to and from a string (e.g. "1.2.3.4"). - /// - internal class VersionConverter : JsonConverter - { - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - writer.WriteNull(); - else if (value is Version) - writer.WriteValue(value.ToString()); - else - throw new JsonSerializationException("Expected Version object value"); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing property value of the JSON that is being converted. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - return null; - - if (reader.TokenType == JsonToken.String) - { - try - { - var v = new Version((string)reader.Value!); - return v; - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex); - } - } - throw JsonSerializationException.Create(reader, - "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, - reader.Value)); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) => objectType == typeof(Version); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/XmlNodeConverter.cs deleted file mode 100644 index 57492a15c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ /dev/null @@ -1,2226 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if (HAVE_XML_DOCUMENT || HAVE_XLINQ) -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Xml; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if HAVE_XLINQ -using System.Xml.Linq; -#endif -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using System.Runtime.CompilerServices; -using System.Diagnostics.CodeAnalysis; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Converters -{ - #region XmlNodeWrappers -#if HAVE_XML_DOCUMENT - internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument - { - private readonly XmlDocument _document; - - public XmlDocumentWrapper(XmlDocument document) - : base(document) - { - _document = document; - } - - public IXmlNode CreateComment(string? data) - { - return new XmlNodeWrapper(_document.CreateComment(data)); - } - - public IXmlNode CreateTextNode(string? text) - { - return new XmlNodeWrapper(_document.CreateTextNode(text)); - } - - public IXmlNode CreateCDataSection(string? data) - { - return new XmlNodeWrapper(_document.CreateCDataSection(data)); - } - - public IXmlNode CreateWhitespace(string? text) - { - return new XmlNodeWrapper(_document.CreateWhitespace(text)); - } - - public IXmlNode CreateSignificantWhitespace(string? text) - { - return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); - } - - public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) - { - return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); - } - -#if HAVE_XML_DOCUMENT_TYPE - public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) - { - return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); - } -#endif - - public IXmlNode CreateProcessingInstruction(string target, string? data) - { - return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); - } - - public IXmlElement CreateElement(string elementName) - { - return new XmlElementWrapper(_document.CreateElement(elementName)); - } - - public IXmlElement CreateElement(string qualifiedName, string namespaceUri) - { - return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri)); - } - - public IXmlNode CreateAttribute(string name, string? value) - { - XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name)); - attribute.Value = value; - - return attribute; - } - - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) - { - XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)); - attribute.Value = value; - - return attribute; - } - - public IXmlElement? DocumentElement - { - get - { - if (_document.DocumentElement == null) - { - return null; - } - - return new XmlElementWrapper(_document.DocumentElement); - } - } - } - - internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement - { - private readonly XmlElement _element; - - public XmlElementWrapper(XmlElement element) - : base(element) - { - _element = element; - } - - public void SetAttributeNode(IXmlNode attribute) - { - XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute; - - _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode!); - } - - public string GetPrefixOfNamespace(string namespaceUri) - { - return _element.GetPrefixOfNamespace(namespaceUri); - } - - public bool IsEmpty => _element.IsEmpty; - } - - internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration - { - private readonly XmlDeclaration _declaration; - - public XmlDeclarationWrapper(XmlDeclaration declaration) - : base(declaration) - { - _declaration = declaration; - } - - public string Version => _declaration.Version; - - public string Encoding - { - get => _declaration.Encoding; - set => _declaration.Encoding = value; - } - - public string Standalone - { - get => _declaration.Standalone; - set => _declaration.Standalone = value; - } - } - -#if HAVE_XML_DOCUMENT_TYPE - internal class XmlDocumentTypeWrapper : XmlNodeWrapper, IXmlDocumentType - { - private readonly XmlDocumentType _documentType; - - public XmlDocumentTypeWrapper(XmlDocumentType documentType) - : base(documentType) - { - _documentType = documentType; - } - - public string Name => _documentType.Name; - - public string System => _documentType.SystemId; - - public string Public => _documentType.PublicId; - - public string InternalSubset => _documentType.InternalSubset; - - public override string? LocalName => "DOCTYPE"; - } -#endif - - internal class XmlNodeWrapper : IXmlNode - { - private readonly XmlNode _node; - private List? _childNodes; - private List? _attributes; - - public XmlNodeWrapper(XmlNode node) - { - _node = node; - } - - public object? WrappedNode => _node; - - public XmlNodeType NodeType => _node.NodeType; - - public virtual string? LocalName => _node.LocalName; - - public List ChildNodes - { - get - { - // childnodes is read multiple times - // cache results to prevent multiple reads which kills perf in large documents - if (_childNodes == null) - { - if (!_node.HasChildNodes) - { - _childNodes = XmlNodeConverter.EmptyChildNodes; - } - else - { - _childNodes = new List(_node.ChildNodes.Count); - foreach (XmlNode childNode in _node.ChildNodes) - { - _childNodes.Add(WrapNode(childNode)); - } - } - } - - return _childNodes; - } - } - - protected virtual bool HasChildNodes => _node.HasChildNodes; - - internal static IXmlNode WrapNode(XmlNode node) - { - switch (node.NodeType) - { - case XmlNodeType.Element: - return new XmlElementWrapper((XmlElement)node); - case XmlNodeType.XmlDeclaration: - return new XmlDeclarationWrapper((XmlDeclaration)node); -#if HAVE_XML_DOCUMENT_TYPE - case XmlNodeType.DocumentType: - return new XmlDocumentTypeWrapper((XmlDocumentType)node); -#endif - default: - return new XmlNodeWrapper(node); - } - } - - public List Attributes - { - get - { - // attributes is read multiple times - // cache results to prevent multiple reads which kills perf in large documents - if (_attributes == null) - { - if (!HasAttributes) - { - _attributes = XmlNodeConverter.EmptyChildNodes; - } - else - { - _attributes = new List(_node.Attributes.Count); - foreach (XmlAttribute attribute in _node.Attributes) - { - _attributes.Add(WrapNode(attribute)); - } - } - } - - return _attributes; - } - } - - private bool HasAttributes - { - get - { - if (_node is XmlElement element) - { - return element.HasAttributes; - } - - return _node.Attributes?.Count > 0; - } - } - - public IXmlNode? ParentNode - { - get - { - XmlNode node = _node is XmlAttribute attribute ? attribute.OwnerElement : _node.ParentNode; - - if (node == null) - { - return null; - } - - return WrapNode(node); - } - } - - public string? Value - { - get => _node.Value; - set => _node.Value = value; - } - - public IXmlNode AppendChild(IXmlNode newChild) - { - XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)newChild; - _node.AppendChild(xmlNodeWrapper._node); - _childNodes = null; - _attributes = null; - - return newChild; - } - - public string? NamespaceUri => _node.NamespaceURI; - } -#endif -#endregion - -#region Interfaces - internal interface IXmlDocument : IXmlNode - { - IXmlNode CreateComment(string? text); - IXmlNode CreateTextNode(string? text); - IXmlNode CreateCDataSection(string? data); - IXmlNode CreateWhitespace(string? text); - IXmlNode CreateSignificantWhitespace(string? text); - IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone); -#if HAVE_XML_DOCUMENT_TYPE - IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset); -#endif - IXmlNode CreateProcessingInstruction(string target, string? data); - IXmlElement CreateElement(string elementName); - IXmlElement CreateElement(string qualifiedName, string namespaceUri); - IXmlNode CreateAttribute(string name, string? value); - IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value); - - IXmlElement? DocumentElement { get; } - } - - internal interface IXmlDeclaration : IXmlNode - { - string Version { get; } - string Encoding { get; set; } - string Standalone { get; set; } - } - - internal interface IXmlDocumentType : IXmlNode - { - string Name { get; } - string System { get; } - string Public { get; } - string InternalSubset { get; } - } - - internal interface IXmlElement : IXmlNode - { - void SetAttributeNode(IXmlNode attribute); - string GetPrefixOfNamespace(string namespaceUri); - bool IsEmpty { get; } - } - - internal interface IXmlNode - { - XmlNodeType NodeType { get; } - string? LocalName { get; } - List ChildNodes { get; } - List Attributes { get; } - IXmlNode? ParentNode { get; } - string? Value { get; set; } - IXmlNode AppendChild(IXmlNode newChild); - string? NamespaceUri { get; } - object? WrappedNode { get; } - } -#endregion - -#region XNodeWrappers -#if HAVE_XLINQ - internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration - { - internal XDeclaration Declaration { get; } - - public XDeclarationWrapper(XDeclaration declaration) - : base(null) - { - Declaration = declaration; - } - - public override XmlNodeType NodeType => XmlNodeType.XmlDeclaration; - - public string Version => Declaration.Version; - - public string Encoding - { - get => Declaration.Encoding; - set => Declaration.Encoding = value; - } - - public string Standalone - { - get => Declaration.Standalone; - set => Declaration.Standalone = value; - } - } - - internal class XDocumentTypeWrapper : XObjectWrapper, IXmlDocumentType - { - private readonly XDocumentType _documentType; - - public XDocumentTypeWrapper(XDocumentType documentType) - : base(documentType) - { - _documentType = documentType; - } - - public string Name => _documentType.Name; - - public string System => _documentType.SystemId; - - public string Public => _documentType.PublicId; - - public string InternalSubset => _documentType.InternalSubset; - - public override string? LocalName => "DOCTYPE"; - } - - internal class XDocumentWrapper : XContainerWrapper, IXmlDocument - { - private XDocument Document => (XDocument)WrappedNode!; - - public XDocumentWrapper(XDocument document) - : base(document) - { - } - - public override List ChildNodes - { - get - { - List childNodes = base.ChildNodes; - if (Document.Declaration != null && (childNodes.Count == 0 || childNodes[0].NodeType != XmlNodeType.XmlDeclaration)) - { - childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration)); - } - - return childNodes; - } - } - - protected override bool HasChildNodes - { - get - { - if (base.HasChildNodes) - { - return true; - } - - return Document.Declaration != null; - } - } - - public IXmlNode CreateComment(string? text) - { - return new XObjectWrapper(new XComment(text)); - } - - public IXmlNode CreateTextNode(string? text) - { - return new XObjectWrapper(new XText(text)); - } - - public IXmlNode CreateCDataSection(string? data) - { - return new XObjectWrapper(new XCData(data)); - } - - public IXmlNode CreateWhitespace(string? text) - { - return new XObjectWrapper(new XText(text)); - } - - public IXmlNode CreateSignificantWhitespace(string? text) - { - return new XObjectWrapper(new XText(text)); - } - - public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) - { - return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); - } - - public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) - { - return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); - } - - public IXmlNode CreateProcessingInstruction(string target, string? data) - { - return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); - } - - public IXmlElement CreateElement(string elementName) - { - return new XElementWrapper(new XElement(elementName)); - } - - public IXmlElement CreateElement(string qualifiedName, string namespaceUri) - { - string localName = MiscellaneousUtils.GetLocalName(qualifiedName); - return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri))); - } - - public IXmlNode CreateAttribute(string name, string? value) - { - return new XAttributeWrapper(new XAttribute(name, value)); - } - - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) - { - string localName = MiscellaneousUtils.GetLocalName(qualifiedName); - return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value)); - } - - public IXmlElement? DocumentElement - { - get - { - if (Document.Root == null) - { - return null; - } - - return new XElementWrapper(Document.Root); - } - } - - public override IXmlNode AppendChild(IXmlNode newChild) - { - if (newChild is XDeclarationWrapper declarationWrapper) - { - Document.Declaration = declarationWrapper.Declaration; - return declarationWrapper; - } - else - { - return base.AppendChild(newChild); - } - } - } - - internal class XTextWrapper : XObjectWrapper - { - private XText Text => (XText)WrappedNode!; - - public XTextWrapper(XText text) - : base(text) - { - } - - public override string? Value - { - get => Text.Value; - set => Text.Value = value; - } - - public override IXmlNode? ParentNode - { - get - { - if (Text.Parent == null) - { - return null; - } - - return XContainerWrapper.WrapNode(Text.Parent); - } - } - } - - internal class XCommentWrapper : XObjectWrapper - { - private XComment Text => (XComment)WrappedNode!; - - public XCommentWrapper(XComment text) - : base(text) - { - } - - public override string? Value - { - get => Text.Value; - set => Text.Value = value; - } - - public override IXmlNode? ParentNode - { - get - { - if (Text.Parent == null) - { - return null; - } - - return XContainerWrapper.WrapNode(Text.Parent); - } - } - } - - internal class XProcessingInstructionWrapper : XObjectWrapper - { - private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)WrappedNode!; - - public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction) - : base(processingInstruction) - { - } - - public override string? LocalName => ProcessingInstruction.Target; - - public override string? Value - { - get => ProcessingInstruction.Data; - set => ProcessingInstruction.Data = value; - } - } - - internal class XContainerWrapper : XObjectWrapper - { - private List? _childNodes; - - private XContainer Container => (XContainer)WrappedNode!; - - public XContainerWrapper(XContainer container) - : base(container) - { - } - - public override List ChildNodes - { - get - { - // childnodes is read multiple times - // cache results to prevent multiple reads which kills perf in large documents - if (_childNodes == null) - { - if (!HasChildNodes) - { - _childNodes = XmlNodeConverter.EmptyChildNodes; - } - else - { - _childNodes = new List(); - foreach (XNode node in Container.Nodes()) - { - _childNodes.Add(WrapNode(node)); - } - } - } - - return _childNodes; - } - } - - protected virtual bool HasChildNodes => Container.LastNode != null; - - public override IXmlNode? ParentNode - { - get - { - if (Container.Parent == null) - { - return null; - } - - return WrapNode(Container.Parent); - } - } - - internal static IXmlNode WrapNode(XObject node) - { - if (node is XDocument document) - { - return new XDocumentWrapper(document); - } - - if (node is XElement element) - { - return new XElementWrapper(element); - } - - if (node is XContainer container) - { - return new XContainerWrapper(container); - } - - if (node is XProcessingInstruction pi) - { - return new XProcessingInstructionWrapper(pi); - } - - if (node is XText text) - { - return new XTextWrapper(text); - } - - if (node is XComment comment) - { - return new XCommentWrapper(comment); - } - - if (node is XAttribute attribute) - { - return new XAttributeWrapper(attribute); - } - - if (node is XDocumentType type) - { - return new XDocumentTypeWrapper(type); - } - - return new XObjectWrapper(node); - } - - public override IXmlNode AppendChild(IXmlNode newChild) - { - Container.Add(newChild.WrappedNode); - _childNodes = null; - - return newChild; - } - } - - internal class XObjectWrapper : IXmlNode - { - private readonly XObject? _xmlObject; - - public XObjectWrapper(XObject? xmlObject) - { - _xmlObject = xmlObject; - } - - public object? WrappedNode => _xmlObject; - - public virtual XmlNodeType NodeType => _xmlObject?.NodeType ?? XmlNodeType.None; - - public virtual string? LocalName => null; - - public virtual List ChildNodes => XmlNodeConverter.EmptyChildNodes; - - public virtual List Attributes => XmlNodeConverter.EmptyChildNodes; - - public virtual IXmlNode? ParentNode => null; - - public virtual string? Value - { - get => null; - set => throw new InvalidOperationException(); - } - - public virtual IXmlNode AppendChild(IXmlNode newChild) - { - throw new InvalidOperationException(); - } - - public virtual string? NamespaceUri => null; - } - - internal class XAttributeWrapper : XObjectWrapper - { - private XAttribute Attribute => (XAttribute)WrappedNode!; - - public XAttributeWrapper(XAttribute attribute) - : base(attribute) - { - } - - public override string? Value - { - get => Attribute.Value; - set => Attribute.Value = value; - } - - public override string? LocalName => Attribute.Name.LocalName; - - public override string? NamespaceUri => Attribute.Name.NamespaceName; - - public override IXmlNode? ParentNode - { - get - { - if (Attribute.Parent == null) - { - return null; - } - - return XContainerWrapper.WrapNode(Attribute.Parent); - } - } - } - - internal class XElementWrapper : XContainerWrapper, IXmlElement - { - private List? _attributes; - - private XElement Element => (XElement)WrappedNode!; - - public XElementWrapper(XElement element) - : base(element) - { - } - - public void SetAttributeNode(IXmlNode attribute) - { - XObjectWrapper wrapper = (XObjectWrapper)attribute; - Element.Add(wrapper.WrappedNode); - _attributes = null; - } - - public override List Attributes - { - get - { - // attributes is read multiple times - // cache results to prevent multiple reads which kills perf in large documents - if (_attributes == null) - { - if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri!)) - { - _attributes = XmlNodeConverter.EmptyChildNodes; - } - else - { - _attributes = new List(); - foreach (XAttribute attribute in Element.Attributes()) - { - _attributes.Add(new XAttributeWrapper(attribute)); - } - - // ensure elements created with a namespace but no namespace attribute are converted correctly - // e.g. new XElement("{http://example.com}MyElement"); - string namespaceUri = NamespaceUri!; - if (HasImplicitNamespaceAttribute(namespaceUri)) - { - _attributes.Insert(0, new XAttributeWrapper(new XAttribute("xmlns", namespaceUri))); - } - } - } - - return _attributes; - } - } - - private bool HasImplicitNamespaceAttribute(string namespaceUri) - { - if (!StringUtils.IsNullOrEmpty(namespaceUri) && namespaceUri != ParentNode?.NamespaceUri) - { - if (StringUtils.IsNullOrEmpty(GetPrefixOfNamespace(namespaceUri))) - { - bool namespaceDeclared = false; - - if (Element.HasAttributes) - { - foreach (XAttribute attribute in Element.Attributes()) - { - if (attribute.Name.LocalName == "xmlns" && StringUtils.IsNullOrEmpty(attribute.Name.NamespaceName) && attribute.Value == namespaceUri) - { - namespaceDeclared = true; - } - } - } - - if (!namespaceDeclared) - { - return true; - } - } - } - - return false; - } - - public override IXmlNode AppendChild(IXmlNode newChild) - { - IXmlNode result = base.AppendChild(newChild); - _attributes = null; - return result; - } - - public override string? Value - { - get => Element.Value; - set => Element.Value = value; - } - - public override string? LocalName => Element.Name.LocalName; - - public override string? NamespaceUri => Element.Name.NamespaceName; - - public string GetPrefixOfNamespace(string namespaceUri) - { - return Element.GetPrefixOfNamespace(namespaceUri); - } - - public bool IsEmpty => Element.IsEmpty; - } -#endif -#endregion - - /// - /// Converts XML to and from JSON. - /// - internal class XmlNodeConverter : JsonConverter - { - internal static readonly List EmptyChildNodes = new List(); - - private const string TextName = "#text"; - private const string CommentName = "#comment"; - private const string CDataName = "#cdata-section"; - private const string WhitespaceName = "#whitespace"; - private const string SignificantWhitespaceName = "#significant-whitespace"; - private const string DeclarationName = "?xml"; - private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json"; - - /// - /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements. - /// - /// The name of the deserialized root element. - public string? DeserializeRootElementName { get; set; } - - /// - /// Gets or sets a value to indicate whether to write the Json.NET array attribute. - /// This attribute helps preserve arrays when converting the written XML back to JSON. - /// - /// true if the array attribute is written to the XML; otherwise, false. - public bool WriteArrayAttribute { get; set; } - - /// - /// Gets or sets a value indicating whether to write the root JSON object. - /// - /// true if the JSON root object is omitted; otherwise, false. - public bool OmitRootObject { get; set; } - - /// - /// Gets or sets a value indicating whether to encode special characters when converting JSON to XML. - /// If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify - /// XML namespaces, attributes or processing directives. Instead special characters are encoded and written - /// as part of the XML element name. - /// - /// true if special characters are encoded; otherwise, false. - public bool EncodeSpecialCharacters { get; set; } - - #region Writing - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The calling serializer. - /// The value. - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - IXmlNode node = WrapXml(value); - - XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); - PushParentNamespaces(node, manager); - - if (!OmitRootObject) - { - writer.WriteStartObject(); - } - - SerializeNode(writer, node, manager, !OmitRootObject); - - if (!OmitRootObject) - { - writer.WriteEndObject(); - } - } - - private IXmlNode WrapXml(object value) - { -#if HAVE_XLINQ - if (value is XObject xObject) - { - return XContainerWrapper.WrapNode(xObject); - } -#endif -#if HAVE_XML_DOCUMENT - if (value is XmlNode node) - { - return XmlNodeWrapper.WrapNode(node); - } -#endif - - throw new ArgumentException("Value must be an XML object.", nameof(value)); - } - - private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) - { - List? parentElements = null; - - IXmlNode? parent = node; - while ((parent = parent.ParentNode) != null) - { - if (parent.NodeType == XmlNodeType.Element) - { - if (parentElements == null) - { - parentElements = new List(); - } - - parentElements.Add(parent); - } - } - - if (parentElements != null) - { - parentElements.Reverse(); - - foreach (IXmlNode parentElement in parentElements) - { - manager.PushScope(); - foreach (IXmlNode attribute in parentElement.Attributes) - { - if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns") - { - manager.AddNamespace(attribute.LocalName, attribute.Value); - } - } - } - } - } - - private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) - { - string? prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) - ? null - : manager.LookupPrefix(node.NamespaceUri); - - if (!StringUtils.IsNullOrEmpty(prefix)) - { - return prefix + ":" + XmlConvert.DecodeName(node.LocalName); - } - else - { - return XmlConvert.DecodeName(node.LocalName); - } - } - - private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager) - { - switch (node.NodeType) - { - case XmlNodeType.Attribute: - if (node.NamespaceUri == JsonNamespaceUri) - { - return "$" + node.LocalName; - } - else - { - return "@" + ResolveFullName(node, manager); - } - case XmlNodeType.CDATA: - return CDataName; - case XmlNodeType.Comment: - return CommentName; - case XmlNodeType.Element: - if (node.NamespaceUri == JsonNamespaceUri) - { - return "$" + node.LocalName; - } - else - { - return ResolveFullName(node, manager); - } - case XmlNodeType.ProcessingInstruction: - return "?" + ResolveFullName(node, manager); - case XmlNodeType.DocumentType: - return "!" + ResolveFullName(node, manager); - case XmlNodeType.XmlDeclaration: - return DeclarationName; - case XmlNodeType.SignificantWhitespace: - return SignificantWhitespaceName; - case XmlNodeType.Text: - return TextName; - case XmlNodeType.Whitespace: - return WhitespaceName; - default: - throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType); - } - } - - private bool IsArray(IXmlNode node) - { - foreach (IXmlNode attribute in node.Attributes) - { - if (attribute.LocalName == "Array" && attribute.NamespaceUri == JsonNamespaceUri) - { - return XmlConvert.ToBoolean(attribute.Value); - } - } - - return false; - } - - private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) - { - switch (node.ChildNodes.Count) - { - case 0: - { - // nothing to serialize - break; - } - case 1: - { - // avoid grouping when there is only one node - string nodeName = GetPropertyName(node.ChildNodes[0], manager); - WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName); - break; - } - default: - { - // check whether nodes have the same name - // if they don't then group into dictionary together by name - - // value of dictionary will be a single IXmlNode when there is one for a name, - // or a List when there are multiple - Dictionary? nodesGroupedByName = null; - - string? nodeName = null; - - for (int i = 0; i < node.ChildNodes.Count; i++) - { - IXmlNode childNode = node.ChildNodes[i]; - string currentNodeName = GetPropertyName(childNode, manager); - - if (nodesGroupedByName == null) - { - if (nodeName == null) - { - nodeName = currentNodeName; - } - else if (currentNodeName == nodeName) - { - // current node name matches others - } - else - { - nodesGroupedByName = new Dictionary(); - if (i > 1) - { - List nodes = new List(i); - for (int j = 0; j < i; j++) - { - nodes.Add(node.ChildNodes[j]); - } - nodesGroupedByName.Add(nodeName, nodes); - } - else - { - nodesGroupedByName.Add(nodeName, node.ChildNodes[0]); - } - nodesGroupedByName.Add(currentNodeName, childNode); - } - } - else - { - if (!nodesGroupedByName.TryGetValue(currentNodeName, out object value)) - { - nodesGroupedByName.Add(currentNodeName, childNode); - } - else - { - if (!(value is List nodes)) - { - nodes = new List {(IXmlNode)value!}; - nodesGroupedByName[currentNodeName] = nodes; - } - - nodes.Add(childNode); - } - } - } - - if (nodesGroupedByName == null) - { - WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName!); - } - else - { - // loop through grouped nodes. write single name instances as normal, - // write multiple names together in an array - foreach (KeyValuePair nodeNameGroup in nodesGroupedByName) - { - if (nodeNameGroup.Value is List nodes) - { - WriteGroupedNodes(writer, manager, writePropertyName, nodes, nodeNameGroup.Key); - } - else - { - WriteGroupedNodes(writer, manager, writePropertyName, (IXmlNode)nodeNameGroup.Value, nodeNameGroup.Key); - } - } - } - break; - } - } - } - - private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, List groupedNodes, string elementNames) - { - bool writeArray = groupedNodes.Count != 1 || IsArray(groupedNodes[0]); - - if (!writeArray) - { - SerializeNode(writer, groupedNodes[0], manager, writePropertyName); - } - else - { - if (writePropertyName) - { - writer.WritePropertyName(elementNames); - } - - writer.WriteStartArray(); - - for (int i = 0; i < groupedNodes.Count; i++) - { - SerializeNode(writer, groupedNodes[i], manager, false); - } - - writer.WriteEndArray(); - } - } - - private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, IXmlNode node, string elementNames) - { - bool writeArray = IsArray(node); - - if (!writeArray) - { - SerializeNode(writer, node, manager, writePropertyName); - } - else - { - if (writePropertyName) - { - writer.WritePropertyName(elementNames); - } - - writer.WriteStartArray(); - - SerializeNode(writer, node, manager, false); - - writer.WriteEndArray(); - } - } - - private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) - { - switch (node.NodeType) - { - case XmlNodeType.Document: - case XmlNodeType.DocumentFragment: - SerializeGroupedNodes(writer, node, manager, writePropertyName); - break; - case XmlNodeType.Element: - if (IsArray(node) && AllSameName(node) && node.ChildNodes.Count > 0) - { - SerializeGroupedNodes(writer, node, manager, false); - } - else - { - manager.PushScope(); - - foreach (IXmlNode attribute in node.Attributes) - { - if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/") - { - string namespacePrefix = (attribute.LocalName != "xmlns") - ? XmlConvert.DecodeName(attribute.LocalName) - : string.Empty; - string? namespaceUri = attribute.Value; - if (namespaceUri == null) - { - throw new JsonSerializationException("Namespace attribute must have a value."); - } - - manager.AddNamespace(namespacePrefix, namespaceUri); - } - } - - if (writePropertyName) - { - writer.WritePropertyName(GetPropertyName(node, manager)); - } - - if (!ValueAttributes(node.Attributes) && node.ChildNodes.Count == 1 - && node.ChildNodes[0].NodeType == XmlNodeType.Text) - { - // write elements with a single text child as a name value pair - writer.WriteValue(node.ChildNodes[0].Value); - } - else if (node.ChildNodes.Count == 0 && node.Attributes.Count == 0) - { - IXmlElement element = (IXmlElement)node; - - // empty element - if (element.IsEmpty) - { - writer.WriteNull(); - } - else - { - writer.WriteValue(string.Empty); - } - } - else - { - writer.WriteStartObject(); - - for (int i = 0; i < node.Attributes.Count; i++) - { - SerializeNode(writer, node.Attributes[i], manager, true); - } - - SerializeGroupedNodes(writer, node, manager, true); - - writer.WriteEndObject(); - } - - manager.PopScope(); - } - - break; - case XmlNodeType.Comment: - if (writePropertyName) - { - writer.WriteComment(node.Value); - } - break; - case XmlNodeType.Attribute: - case XmlNodeType.Text: - case XmlNodeType.CDATA: - case XmlNodeType.ProcessingInstruction: - case XmlNodeType.Whitespace: - case XmlNodeType.SignificantWhitespace: - if (node.NamespaceUri == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri) - { - return; - } - - if (node.NamespaceUri == JsonNamespaceUri) - { - if (node.LocalName == "Array") - { - return; - } - } - - if (writePropertyName) - { - writer.WritePropertyName(GetPropertyName(node, manager)); - } - writer.WriteValue(node.Value); - break; - case XmlNodeType.XmlDeclaration: - IXmlDeclaration declaration = (IXmlDeclaration)node; - writer.WritePropertyName(GetPropertyName(node, manager)); - writer.WriteStartObject(); - - if (!StringUtils.IsNullOrEmpty(declaration.Version)) - { - writer.WritePropertyName("@version"); - writer.WriteValue(declaration.Version); - } - if (!StringUtils.IsNullOrEmpty(declaration.Encoding)) - { - writer.WritePropertyName("@encoding"); - writer.WriteValue(declaration.Encoding); - } - if (!StringUtils.IsNullOrEmpty(declaration.Standalone)) - { - writer.WritePropertyName("@standalone"); - writer.WriteValue(declaration.Standalone); - } - - writer.WriteEndObject(); - break; - case XmlNodeType.DocumentType: - IXmlDocumentType documentType = (IXmlDocumentType)node; - writer.WritePropertyName(GetPropertyName(node, manager)); - writer.WriteStartObject(); - - if (!StringUtils.IsNullOrEmpty(documentType.Name)) - { - writer.WritePropertyName("@name"); - writer.WriteValue(documentType.Name); - } - if (!StringUtils.IsNullOrEmpty(documentType.Public)) - { - writer.WritePropertyName("@public"); - writer.WriteValue(documentType.Public); - } - if (!StringUtils.IsNullOrEmpty(documentType.System)) - { - writer.WritePropertyName("@system"); - writer.WriteValue(documentType.System); - } - if (!StringUtils.IsNullOrEmpty(documentType.InternalSubset)) - { - writer.WritePropertyName("@internalSubset"); - writer.WriteValue(documentType.InternalSubset); - } - - writer.WriteEndObject(); - break; - default: - throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType); - } - } - - private static bool AllSameName(IXmlNode node) - { - foreach (IXmlNode childNode in node.ChildNodes) - { - if (childNode.LocalName != node.LocalName) - { - return false; - } - } - return true; - } -#endregion - - #region Reading - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - switch (reader.TokenType) - { - case JsonToken.Null: - return null; - case JsonToken.StartObject: - break; - default: - throw JsonSerializationException.Create(reader, "XmlNodeConverter can only convert JSON that begins with an object."); - } - - XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); - IXmlDocument? document = null; - IXmlNode? rootNode = null; - -#if HAVE_XLINQ - if (typeof(XObject).IsAssignableFrom(objectType)) - { - if (objectType != typeof(XContainer) - && objectType != typeof(XDocument) - && objectType != typeof(XElement) - && objectType != typeof(XNode) - && objectType != typeof(XObject)) - { - throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XDocument, XElement, XContainer, XNode or XObject."); - } - - XDocument d = new XDocument(); - document = new XDocumentWrapper(d); - rootNode = document; - } -#endif -#if HAVE_XML_DOCUMENT - if (typeof(XmlNode).IsAssignableFrom(objectType)) - { - if (objectType != typeof(XmlDocument) - && objectType != typeof(XmlElement) - && objectType != typeof(XmlNode)) - { - throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XmlDocument, XmlElement or XmlNode."); - } - - XmlDocument d = new XmlDocument(); -#if HAVE_XML_DOCUMENT_TYPE - // prevent http request when resolving any DTD references - d.XmlResolver = null; -#endif - - document = new XmlDocumentWrapper(d); - rootNode = document; - } -#endif - - if (document == null || rootNode == null) - { - throw JsonSerializationException.Create(reader, "Unexpected type when converting XML: " + objectType); - } - - if (!StringUtils.IsNullOrEmpty(DeserializeRootElementName)) - { - ReadElement(reader, document, rootNode, DeserializeRootElementName, manager); - } - else - { - reader.ReadAndAssert(); - DeserializeNode(reader, document, manager, rootNode); - } - -#if HAVE_XLINQ - if (objectType == typeof(XElement)) - { - XElement element = (XElement)document.DocumentElement!.WrappedNode!; - element.Remove(); - - return element; - } -#endif -#if HAVE_XML_DOCUMENT - if (objectType == typeof(XmlElement)) - { - return document.DocumentElement!.WrappedNode; - } -#endif - - return document.WrappedNode; - } - - private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode) - { - if (!EncodeSpecialCharacters) - { - switch (propertyName) - { - case TextName: - currentNode.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader))); - return; - case CDataName: - currentNode.AppendChild(document.CreateCDataSection(ConvertTokenToXmlValue(reader))); - return; - case WhitespaceName: - currentNode.AppendChild(document.CreateWhitespace(ConvertTokenToXmlValue(reader))); - return; - case SignificantWhitespaceName: - currentNode.AppendChild(document.CreateSignificantWhitespace(ConvertTokenToXmlValue(reader))); - return; - default: - // processing instructions and the xml declaration start with ? - if (!StringUtils.IsNullOrEmpty(propertyName) && propertyName[0] == '?') - { - CreateInstruction(reader, document, currentNode, propertyName); - return; - } -#if HAVE_XML_DOCUMENT_TYPE - else if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase)) - { - CreateDocumentType(reader, document, currentNode); - return; - } -#endif - break; - } - } - - if (reader.TokenType == JsonToken.StartArray) - { - // handle nested arrays - ReadArrayElements(reader, document, propertyName, currentNode, manager); - return; - } - - // have to wait until attributes have been parsed before creating element - // attributes may contain namespace info used by the element - ReadElement(reader, document, currentNode, propertyName, manager); - } - - private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager) - { - if (StringUtils.IsNullOrEmpty(propertyName)) - { - throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML."); - } - - Dictionary? attributeNameValues = null; - string? elementPrefix = null; - - if (!EncodeSpecialCharacters) - { - attributeNameValues = ShouldReadInto(reader) - ? ReadAttributeElements(reader, manager) - : null; - elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); - - if (propertyName.StartsWith('@')) - { - string attributeName = propertyName.Substring(1); - string? attributePrefix = MiscellaneousUtils.GetPrefix(attributeName); - - AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); - return; - } - - if (propertyName.StartsWith('$')) - { - switch (propertyName) - { - case JsonTypeReflector.ArrayValuesPropertyName: - propertyName = propertyName.Substring(1); - elementPrefix = manager.LookupPrefix(JsonNamespaceUri); - CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); - return; - case JsonTypeReflector.IdPropertyName: - case JsonTypeReflector.RefPropertyName: - case JsonTypeReflector.TypePropertyName: - case JsonTypeReflector.ValuePropertyName: - string attributeName = propertyName.Substring(1); - string attributePrefix = manager.LookupPrefix(JsonNamespaceUri); - AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); - return; - } - } - } - else - { - if (ShouldReadInto(reader)) - { - reader.ReadAndAssert(); - } - } - - CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); - } - - private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string? elementPrefix, Dictionary? attributeNameValues) - { - IXmlElement element = CreateElement(elementName, document, elementPrefix, manager); - - currentNode.AppendChild(element); - - if (attributeNameValues != null) - { - // add attributes to newly created element - foreach (KeyValuePair nameValue in attributeNameValues) - { - string encodedName = XmlConvert.EncodeName(nameValue.Key); - string? attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key); - - IXmlNode attribute = - (!StringUtils.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value) : document.CreateAttribute(encodedName, nameValue.Value); - - element.SetAttributeNode(attribute); - } - } - - switch (reader.TokenType) - { - case JsonToken.String: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Boolean: - case JsonToken.Date: - case JsonToken.Bytes: - string? text = ConvertTokenToXmlValue(reader); - if (text != null) - { - element.AppendChild(document.CreateTextNode(text)); - } - break; - case JsonToken.Null: - - // empty element. do nothing - break; - case JsonToken.EndObject: - - // finished element will have no children to deserialize - manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); - break; - default: - manager.PushScope(); - DeserializeNode(reader, document, manager, element); - manager.PopScope(); - manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); - break; - } - } - - private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string? attributePrefix) - { - if (currentNode.NodeType == XmlNodeType.Document) - { - throw JsonSerializationException.Create(reader, "JSON root object has property '{0}' that will be converted to an attribute. A root object cannot have any attribute properties. Consider specifying a DeserializeRootElementName.".FormatWith(CultureInfo.InvariantCulture, propertyName)); - } - - string encodedName = XmlConvert.EncodeName(attributeName); - string? attributeValue = ConvertTokenToXmlValue(reader); - - IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) - ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix), attributeValue) - : document.CreateAttribute(encodedName, attributeValue); - - ((IXmlElement)currentNode).SetAttributeNode(attribute); - } - - private static string? ConvertTokenToXmlValue(JsonReader reader) - { - switch (reader.TokenType) - { - case JsonToken.String: - return reader.Value?.ToString(); - case JsonToken.Integer: -#if HAVE_BIG_INTEGER - if (reader.Value is BigInteger i) - { - return i.ToString(CultureInfo.InvariantCulture); - } -#endif - return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture)); - case JsonToken.Float: - { - if (reader.Value is decimal d) - { - return XmlConvert.ToString(d); - } - - if (reader.Value is float f) - { - return XmlConvert.ToString(f); - } - - return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture)); - } - case JsonToken.Boolean: - return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture)); - case JsonToken.Date: - { -#if HAVE_DATE_TIME_OFFSET - if (reader.Value is DateTimeOffset offset) - { - return XmlConvert.ToString(offset); - } - -#endif - DateTime d = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture); -#if !PORTABLE || NETSTANDARD1_3 - return XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind)); -#else - return d.ToString(DateTimeUtils.ToDateTimeFormat(d.Kind), CultureInfo.InvariantCulture); -#endif - } - case JsonToken.Bytes: - return Convert.ToBase64String((byte[])reader.Value!); - case JsonToken.Null: - return null; - default: - throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } - - private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager) - { - string? elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); - - IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager); - - currentNode.AppendChild(nestedArrayElement); - - int count = 0; - while (reader.Read() && reader.TokenType != JsonToken.EndArray) - { - DeserializeValue(reader, document, manager, propertyName, nestedArrayElement); - count++; - } - - if (WriteArrayAttribute) - { - AddJsonArrayAttribute(nestedArrayElement, document); - } - - if (count == 1 && WriteArrayAttribute) - { - foreach (IXmlNode childNode in nestedArrayElement.ChildNodes) - { - if (childNode is IXmlElement element && element.LocalName == propertyName) - { - AddJsonArrayAttribute(element, document); - break; - } - } - } - } - - private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document) - { - element.SetAttributeNode(document.CreateAttribute("json:Array", JsonNamespaceUri, "true")); - -#if HAVE_XLINQ - // linq to xml doesn't automatically include prefixes via the namespace manager - if (element is XElementWrapper) - { - if (element.GetPrefixOfNamespace(JsonNamespaceUri) == null) - { - element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", JsonNamespaceUri)); - } - } -#endif - } - - private bool ShouldReadInto(JsonReader reader) - { - // a string token means the element only has a single text child - switch (reader.TokenType) - { - case JsonToken.String: - case JsonToken.Null: - case JsonToken.Boolean: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Date: - case JsonToken.Bytes: - case JsonToken.StartConstructor: - return false; - } - - return true; - } - - private Dictionary? ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) - { - Dictionary? attributeNameValues = null; - bool finished = false; - - // read properties until first non-attribute is encountered - while (!finished && reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - string attributeName = reader.Value!.ToString(); - - if (!StringUtils.IsNullOrEmpty(attributeName)) - { - char firstChar = attributeName[0]; - string? attributeValue; - - switch (firstChar) - { - case '@': - if (attributeNameValues == null) - { - attributeNameValues = new Dictionary(); - } - - attributeName = attributeName.Substring(1); - reader.ReadAndAssert(); - attributeValue = ConvertTokenToXmlValue(reader); - attributeNameValues.Add(attributeName, attributeValue); - - if (IsNamespaceAttribute(attributeName, out string? namespacePrefix)) - { - manager.AddNamespace(namespacePrefix, attributeValue); - } - break; - case '$': - switch (attributeName) - { - case JsonTypeReflector.ArrayValuesPropertyName: - case JsonTypeReflector.IdPropertyName: - case JsonTypeReflector.RefPropertyName: - case JsonTypeReflector.TypePropertyName: - case JsonTypeReflector.ValuePropertyName: - // check that JsonNamespaceUri is in scope - // if it isn't then add it to document and namespace manager - string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri); - if (jsonPrefix == null) - { - if (attributeNameValues == null) - { - attributeNameValues = new Dictionary(); - } - - // ensure that the prefix used is free - int? i = null; - while (manager.LookupNamespace("json" + i) != null) - { - i = i.GetValueOrDefault() + 1; - } - jsonPrefix = "json" + i; - - attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri); - manager.AddNamespace(jsonPrefix, JsonNamespaceUri); - } - - // special case $values, it will have a non-primitive value - if (attributeName == JsonTypeReflector.ArrayValuesPropertyName) - { - finished = true; - break; - } - - attributeName = attributeName.Substring(1); - reader.ReadAndAssert(); - - if (!JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) - { - throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); - } - - if (attributeNameValues == null) - { - attributeNameValues = new Dictionary(); - } - - attributeValue = reader.Value?.ToString(); - attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue); - break; - default: - finished = true; - break; - } - break; - default: - finished = true; - break; - } - } - else - { - finished = true; - } - - break; - case JsonToken.EndObject: - case JsonToken.Comment: - finished = true; - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); - } - } - - return attributeNameValues; - } - - private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName) - { - if (propertyName == DeclarationName) - { - string? version = null; - string? encoding = null; - string? standalone = null; - while (reader.Read() && reader.TokenType != JsonToken.EndObject) - { - switch (reader.Value?.ToString()) - { - case "@version": - reader.ReadAndAssert(); - version = ConvertTokenToXmlValue(reader); - break; - case "@encoding": - reader.ReadAndAssert(); - encoding = ConvertTokenToXmlValue(reader); - break; - case "@standalone": - reader.ReadAndAssert(); - standalone = ConvertTokenToXmlValue(reader); - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); - } - } - - IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone); - currentNode.AppendChild(declaration); - } - else - { - IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)); - currentNode.AppendChild(instruction); - } - } - -#if HAVE_XML_DOCUMENT_TYPE - private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode) - { - string? name = null; - string? publicId = null; - string? systemId = null; - string? internalSubset = null; - while (reader.Read() && reader.TokenType != JsonToken.EndObject) - { - switch (reader.Value?.ToString()) - { - case "@name": - reader.ReadAndAssert(); - name = ConvertTokenToXmlValue(reader); - break; - case "@public": - reader.ReadAndAssert(); - publicId = ConvertTokenToXmlValue(reader); - break; - case "@system": - reader.ReadAndAssert(); - systemId = ConvertTokenToXmlValue(reader); - break; - case "@internalSubset": - reader.ReadAndAssert(); - internalSubset = ConvertTokenToXmlValue(reader); - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); - } - } - - IXmlNode documentType = document.CreateXmlDocumentType(name, publicId, systemId, internalSubset); - currentNode.AppendChild(documentType); - } -#endif - - private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) - { - string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName); - string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); - - IXmlElement element = (!StringUtils.IsNullOrEmpty(ns)) ? document.CreateElement(encodeName, ns) : document.CreateElement(encodeName); - - return element; - } - - private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode) - { - do - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null) - { - throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); - } - - string propertyName = reader.Value!.ToString(); - reader.ReadAndAssert(); - - if (reader.TokenType == JsonToken.StartArray) - { - int count = 0; - while (reader.Read() && reader.TokenType != JsonToken.EndArray) - { - DeserializeValue(reader, document, manager, propertyName, currentNode); - count++; - } - - if (count == 1 && WriteArrayAttribute) - { - MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string? elementPrefix, out string localName); - string ns = - StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); - - foreach (IXmlNode childNode in currentNode.ChildNodes) - { - if (childNode is IXmlElement element && element.LocalName == localName && element.NamespaceUri == ns) - { - AddJsonArrayAttribute(element, document); - break; - } - } - } - } - else - { - DeserializeValue(reader, document, manager, propertyName, currentNode); - } - continue; - case JsonToken.StartConstructor: - string constructorName = reader.Value!.ToString(); - - while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) - { - DeserializeValue(reader, document, manager, constructorName, currentNode); - } - break; - case JsonToken.Comment: - currentNode.AppendChild(document.CreateComment((string)reader.Value!)); - break; - case JsonToken.EndObject: - case JsonToken.EndArray: - return; - default: - throw JsonSerializationException.Create(reader, "Unexpected JsonToken when deserializing node: " + reader.TokenType); - } - } while (reader.Read()); - // don't read if current token is a property. token was already read when parsing element attributes - } - - /// - /// Checks if the is a namespace attribute. - /// - /// Attribute name to test. - /// The attribute name prefix if it has one, otherwise an empty string. - /// true if attribute name is for a namespace attribute, otherwise false. - private bool IsNamespaceAttribute(string attributeName, [NotNullWhen(true)]out string? prefix) - { - if (attributeName.StartsWith("xmlns", StringComparison.Ordinal)) - { - if (attributeName.Length == 5) - { - prefix = string.Empty; - return true; - } - else if (attributeName[5] == ':') - { - prefix = attributeName.Substring(6, attributeName.Length - 6); - return true; - } - } - prefix = null; - return false; - } - - private bool ValueAttributes(List c) - { - foreach (IXmlNode xmlNode in c) - { - if (xmlNode.NamespaceUri == JsonNamespaceUri) - { - continue; - } - - if (xmlNode.NamespaceUri == "http://www.w3.org/2000/xmlns/" && xmlNode.Value == JsonNamespaceUri) - { - continue; - } - - return true; - } - - return false; - } -#endregion - - /// - /// Determines whether this instance can convert the specified value type. - /// - /// Type of the value. - /// - /// true if this instance can convert the specified value type; otherwise, false. - /// - public override bool CanConvert(Type valueType) - { -#if HAVE_XLINQ - if (valueType.AssignableToTypeName("System.Xml.Linq.XObject", false)) - { - return IsXObject(valueType); - } -#endif -#if HAVE_XML_DOCUMENT - if (valueType.AssignableToTypeName("System.Xml.XmlNode", false)) - { - return IsXmlNode(valueType); - } -#endif - - return false; - } - -#if HAVE_XLINQ - [MethodImpl(MethodImplOptions.NoInlining)] - private bool IsXObject(Type valueType) - { - return typeof(XObject).IsAssignableFrom(valueType); - } -#endif - -#if HAVE_XML_DOCUMENT - [MethodImpl(MethodImplOptions.NoInlining)] - private bool IsXmlNode(Type valueType) - { - return typeof(XmlNode).IsAssignableFrom(valueType); - } -#endif - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateFormatHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateFormatHandling.cs deleted file mode 100644 index 6de8325f5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateFormatHandling.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how dates are formatted when writing JSON text. - /// - internal enum DateFormatHandling - { - /// - /// Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z". - /// - IsoDateFormat, - - /// - /// Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/". - /// - MicrosoftDateFormat - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateParseHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateParseHandling.cs deleted file mode 100644 index dedbfeee8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateParseHandling.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed - /// when reading JSON text. - /// - internal enum DateParseHandling - { - /// - /// Date formatted strings are not parsed to a date type and are read as strings. - /// - None = 0, - - /// - /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to - /// . - /// - DateTime = 1, -#if HAVE_DATE_TIME_OFFSET - /// - /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . - /// - DateTimeOffset = 2 -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateTimeZoneHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateTimeZoneHandling.cs deleted file mode 100644 index 6d5c27218..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DateTimeZoneHandling.cs +++ /dev/null @@ -1,60 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how to treat the time value when converting between string and . - /// - internal enum DateTimeZoneHandling - { - /// - /// Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is - /// converted to the local time. - /// - Local = 0, - - /// - /// Treat as a UTC. If the object represents a local time, it is converted to a UTC. - /// - Utc = 1, - - /// - /// Treat as a local time if a is being converted to a string. - /// If a string is being converted to , convert to a local time if a time zone is specified. - /// - Unspecified = 2, - - /// - /// Time zone information should be preserved when converting. - /// - RoundtripKind = 3 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultJsonNameTable.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultJsonNameTable.cs deleted file mode 100644 index 38c56a52f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultJsonNameTable.cs +++ /dev/null @@ -1,165 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// The default JSON name table implementation. - /// - internal class DefaultJsonNameTable : JsonNameTable - { - // used to defeat hashtable DoS attack where someone passes in lots of strings that hash to the same hash code - private static readonly int HashCodeRandomizer; - - static DefaultJsonNameTable() => HashCodeRandomizer = Environment.TickCount; - - /// - /// Initializes a new instance of the class. - /// - public DefaultJsonNameTable() => _entries = new Entry[_mask + 1]; - - private int _count; - private Entry[] _entries; - private int _mask = 31; - - /// - /// Gets a string containing the same characters as the specified range of characters in the given array. - /// - /// The character array containing the name to find. - /// The zero-based index into the array specifying the first character of the name. - /// The number of characters in the name. - /// A string containing the same characters as the specified range of characters in the given array. - public override string? Get(char[] key, int start, int length) - { - if (length == 0) return string.Empty; - - var hashCode = length + HashCodeRandomizer; - hashCode += (hashCode << 7) ^ key[start]; - var end = start + length; - for (var i = start + 1; i < end; i++) hashCode += (hashCode << 7) ^ key[i]; - hashCode -= hashCode >> 17; - hashCode -= hashCode >> 11; - hashCode -= hashCode >> 5; - - // make sure index is evaluated before accessing _entries, otherwise potential race condition causing IndexOutOfRangeException - var index = hashCode & _mask; - var entries = _entries; - - for (var entry = entries[index]; entry != null; entry = entry.Next) - { - if (entry.HashCode == hashCode && TextEquals(entry.Value, key, start, length)) return entry.Value; - } - - return null; - } - - /// - /// Adds the specified string into name table. - /// - /// The string to add. - /// This method is not thread-safe. - /// The resolved string. - public string Add(string key) - { - if (key == null) throw new ArgumentNullException(nameof(key)); - - var length = key.Length; - if (length == 0) return string.Empty; - - var hashCode = length + HashCodeRandomizer; - for (var i = 0; i < key.Length; i++) hashCode += (hashCode << 7) ^ key[i]; - hashCode -= hashCode >> 17; - hashCode -= hashCode >> 11; - hashCode -= hashCode >> 5; - for (var entry = _entries[hashCode & _mask]; entry != null; entry = entry.Next) - { - if (entry.HashCode == hashCode && entry.Value.Equals(key, StringComparison.Ordinal)) return entry.Value; - } - - return AddEntry(key, hashCode); - } - - private string AddEntry(string str, int hashCode) - { - var index = hashCode & _mask; - var entry = new Entry(str, hashCode, _entries[index]); - _entries[index] = entry; - if (_count++ == _mask) Grow(); - return entry.Value; - } - - private void Grow() - { - var entries = _entries; - var newMask = _mask * 2 + 1; - var newEntries = new Entry[newMask + 1]; - - for (var i = 0; i < entries.Length; i++) - { - Entry next; - for (var entry = entries[i]; entry != null; entry = next) - { - var index = entry.HashCode & newMask; - next = entry.Next; - entry.Next = newEntries[index]; - newEntries[index] = entry; - } - } - _entries = newEntries; - _mask = newMask; - } - - private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) - { - if (str1.Length != str2Length) return false; - - for (var i = 0; i < str1.Length; i++) - { - if (str1[i] != str2[str2Start + i]) return false; - } - return true; - } - - private class Entry - { - internal readonly int HashCode; - internal readonly string Value; - - internal Entry(string value, int hashCode, Entry next) - { - Value = value; - HashCode = hashCode; - Next = next; - } - - internal Entry Next; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultValueHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultValueHandling.cs deleted file mode 100644 index 3c621564a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/DefaultValueHandling.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.ComponentModel; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies default value handling options for the . - /// - /// - /// - /// - /// - [Flags] - internal enum DefaultValueHandling - { - /// - /// Include members where the member value is the same as the member's default value when serializing objects. - /// Included members are written to JSON. Has no effect when deserializing. - /// - Include = 0, - - /// - /// Ignore members where the member value is the same as the member's default value when serializing objects - /// so that it is not written to JSON. - /// This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers, - /// decimals and floating point numbers; and false for booleans). The default value ignored can be changed by - /// placing the on the property. - /// - Ignore = 1, - - /// - /// Members with a default value but no JSON will be set to their default value when deserializing. - /// - Populate = 2, - - /// - /// Ignore members where the member value is the same as the member's default value when serializing objects - /// and set members to their default value when deserializing. - /// - IgnoreAndPopulate = Ignore | Populate - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatFormatHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatFormatHandling.cs deleted file mode 100644 index 893f6b04b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatFormatHandling.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies float format handling options when writing special floating point numbers, e.g. , - /// and with . - /// - internal enum FloatFormatHandling - { - /// - /// Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity". - /// - String = 0, - - /// - /// Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity. - /// Note that this will produce non-valid JSON. - /// - Symbol = 1, - - /// - /// Write special floating point values as the property's default value in JSON, e.g. 0.0 for a - /// property, null for a of property. - /// - DefaultValue = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatParseHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatParseHandling.cs deleted file mode 100644 index 92d98553b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FloatParseHandling.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. - /// - internal enum FloatParseHandling - { - /// - /// Floating point numbers are parsed to . - /// - Double = 0, - - /// - /// Floating point numbers are parsed to . - /// - Decimal = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FormatterAssemblyStyle.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/FormatterAssemblyStyle.cs deleted file mode 100644 index 86afe39ed..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/FormatterAssemblyStyle.cs +++ /dev/null @@ -1,23 +0,0 @@ -#if HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE -#nullable enable -namespace System.Runtime.Serialization.Formatters -{ - /// - /// Indicates the method that will be used during deserialization for locating and loading assemblies. - /// - [Obsolete("FormatterAssemblyStyle is obsolete. Use TypeNameAssemblyFormatHandling instead.")] - internal enum FormatterAssemblyStyle - { - /// - /// In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the method is used to load the assembly. - /// - Simple = 0, - - /// - /// In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The is used to load the assembly. - /// - Full = 1 - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Formatting.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Formatting.cs deleted file mode 100644 index acdb9ff42..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Formatting.cs +++ /dev/null @@ -1,47 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies formatting options for the . - /// - internal enum Formatting - { - /// - /// No special formatting is applied. This is the default. - /// - None = 0, - - /// - /// Causes child objects to be indented according to the and - /// settings. - /// - Indented = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/IArrayPool.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/IArrayPool.cs deleted file mode 100644 index 8aa033336..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/IArrayPool.cs +++ /dev/null @@ -1,23 +0,0 @@ -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Provides an interface for using pooled arrays. - /// - /// The array type content. - internal interface IArrayPool - { - /// - /// Rent an array from the pool. This array must be returned when it is no longer needed. - /// - /// The minimum required length of the array. The returned array may be longer. - /// The rented array from the pool. This array must be returned when it is no longer needed. - T[] Rent(int minimumLength); - - /// - /// Return an array to the pool. - /// - /// The array that is being returned. - void Return(T[]? array); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/IJsonLineInfo.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/IJsonLineInfo.cs deleted file mode 100644 index 7d700a7da..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/IJsonLineInfo.cs +++ /dev/null @@ -1,62 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Provides an interface to enable a class to return line and position information. - /// - internal interface IJsonLineInfo - { - /// - /// Gets the current line number. - /// - /// - /// The current line number or 0 if no line information is available (for example, when - /// returns false). - /// - int LineNumber { get; } - - /// - /// Gets the current line position. - /// - /// - /// The current line position or 0 if no line information is available (for example, when - /// returns false). - /// - int LinePosition { get; } - - /// - /// Gets a value indicating whether the class can return line information. - /// - /// - /// true if and can be provided; otherwise, false. - /// - bool HasLineInfo(); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonArrayAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonArrayAttribute.cs deleted file mode 100644 index 40876cea3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonArrayAttribute.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the how to serialize the collection. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] - internal sealed class JsonArrayAttribute : JsonContainerAttribute - { - /// - /// Initializes a new instance of the class. - /// - public JsonArrayAttribute() { } - - /// - /// Initializes a new instance of the class with a flag indicating whether the array can - /// contain null items. - /// - /// A flag indicating whether the array can contain null items. - public JsonArrayAttribute(bool allowNullItems) => AllowNullItems = allowNullItems; - - /// - /// Initializes a new instance of the class with the specified container Id. - /// - /// The container Id. - public JsonArrayAttribute(string id) - : base(id) { } - - /// - /// Gets or sets a value indicating whether null items are allowed in the collection. - /// - /// true if null items are allowed in the collection; otherwise, false. - public bool AllowNullItems { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConstructorAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConstructorAttribute.cs deleted file mode 100644 index 137b3aa01..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConstructorAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the to use the specified constructor when deserializing that object. - /// - [AttributeUsage(AttributeTargets.Constructor)] - internal sealed class JsonConstructorAttribute : Attribute { } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonContainerAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonContainerAttribute.cs deleted file mode 100644 index f18d97a4f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonContainerAttribute.cs +++ /dev/null @@ -1,182 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the how to serialize the object. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] - internal abstract class JsonContainerAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - protected JsonContainerAttribute() { } - - /// - /// Initializes a new instance of the class with the specified container Id. - /// - /// The container Id. - protected JsonContainerAttribute(string id) => Id = id; - - // yuck. can't set nullable properties on an attribute in C# - // have to use this approach to get an unset default state - internal bool? _isReference; - internal bool? _itemIsReference; - internal ReferenceLoopHandling? _itemReferenceLoopHandling; - internal TypeNameHandling? _itemTypeNameHandling; - private object[]? _namingStrategyParameters; - private Type? _namingStrategyType; - - /// - /// Gets or sets the description. - /// - /// The description. - public string? Description { get; set; } - - /// - /// Gets or sets the id. - /// - /// The id. - public string? Id { get; set; } - - /// - /// Gets or sets a value that indicates whether to preserve object references. - /// - /// - /// true to keep object reference; otherwise, false. The default is false. - /// - public bool IsReference - { - get => _isReference ?? default; - set => _isReference = value; - } - - /// - /// The parameter list to use when constructing the described by - /// . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the that exactly matches the - /// number, - /// order, and type of these parameters. - /// - /// - /// - /// [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] - /// - /// - public object[]? ItemConverterParameters { get; set; } - - /// - /// Gets or sets the collection's items converter. - /// - /// The collection's items converter. - public Type? ItemConverterType { get; set; } - - /// - /// Gets or sets a value that indicates whether to preserve collection's items references. - /// - /// - /// true to keep collection's items object references; otherwise, false. The default is false. - /// - public bool ItemIsReference - { - get => _itemIsReference ?? default; - set => _itemIsReference = value; - } - - /// - /// Gets or sets the reference loop handling used when serializing the collection's items. - /// - /// The reference loop handling. - public ReferenceLoopHandling ItemReferenceLoopHandling - { - get => _itemReferenceLoopHandling ?? default; - set => _itemReferenceLoopHandling = value; - } - - /// - /// Gets or sets the type name handling used when serializing the collection's items. - /// - /// The type name handling. - public TypeNameHandling ItemTypeNameHandling - { - get => _itemTypeNameHandling ?? default; - set => _itemTypeNameHandling = value; - } - - internal NamingStrategy? NamingStrategyInstance { get; set; } - - /// - /// The parameter list to use when constructing the described by - /// . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the that exactly matches the - /// number, - /// order, and type of these parameters. - /// - /// - /// - /// [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] - /// - /// - public object[]? NamingStrategyParameters - { - get => _namingStrategyParameters; - set - { - _namingStrategyParameters = value; - NamingStrategyInstance = null; - } - } - - /// - /// Gets or sets the of the . - /// - /// The of the . - public Type? NamingStrategyType - { - get => _namingStrategyType; - set - { - _namingStrategyType = value; - NamingStrategyInstance = null; - } - } - - /// - /// Gets or sets the title. - /// - /// The title. - public string? Title { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConvert.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConvert.cs deleted file mode 100644 index 7942cee99..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConvert.cs +++ /dev/null @@ -1,978 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Text; -using System.Xml; -using Elastic.Apm.Libraries.Newtonsoft.Json.Converters; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#if HAVE_XLINQ -using System.Xml.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Provides methods for converting between .NET types and JSON types. - /// - /// - /// - /// - internal static class JsonConvert - { - /// - /// Gets or sets a function that creates default . - /// Default settings are automatically used by serialization methods on , - /// and and on . - /// To serialize without using any default settings create a with - /// . - /// - public static Func? DefaultSettings { get; set; } - - /// - /// Represents JavaScript's boolean value true as a string. This field is read-only. - /// - public static readonly string True = "true"; - - /// - /// Represents JavaScript's boolean value false as a string. This field is read-only. - /// - public static readonly string False = "false"; - - /// - /// Represents JavaScript's null as a string. This field is read-only. - /// - public static readonly string Null = "null"; - - /// - /// Represents JavaScript's undefined as a string. This field is read-only. - /// - public static readonly string Undefined = "undefined"; - - /// - /// Represents JavaScript's positive infinity as a string. This field is read-only. - /// - public static readonly string PositiveInfinity = "Infinity"; - - /// - /// Represents JavaScript's negative infinity as a string. This field is read-only. - /// - public static readonly string NegativeInfinity = "-Infinity"; - - /// - /// Represents JavaScript's NaN as a string. This field is read-only. - /// - public static readonly string NaN = "NaN"; - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(DateTime value) => ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); - - /// - /// Converts the to its JSON string representation using the - /// specified. - /// - /// The value to convert. - /// The format the date will be converted to. - /// The time zone handling when the date is converted to a string. - /// A JSON string representation of the . - public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) - { - var updatedDateTime = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); - - using (var writer = StringUtils.CreateStringWriter(64)) - { - writer.Write('"'); - DateTimeUtils.WriteDateTimeString(writer, updatedDateTime, format, null, CultureInfo.InvariantCulture); - writer.Write('"'); - return writer.ToString(); - } - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(DateTimeOffset value) - { - return ToString(value, DateFormatHandling.IsoDateFormat); - } - - /// - /// Converts the to its JSON string representation using the specified. - /// - /// The value to convert. - /// The format the date will be converted to. - /// A JSON string representation of the . - public static string ToString(DateTimeOffset value, DateFormatHandling format) - { - using (StringWriter writer = StringUtils.CreateStringWriter(64)) - { - writer.Write('"'); - DateTimeUtils.WriteDateTimeOffsetString(writer, value, format, null, CultureInfo.InvariantCulture); - writer.Write('"'); - return writer.ToString(); - } - } -#endif - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(bool value) => value ? True : False; - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(char value) => ToString(char.ToString(value)); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(Enum value) => value.ToString("D"); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(int value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(short value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - - public static string ToString(ushort value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - - public static string ToString(uint value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(long value) => value.ToString(null, CultureInfo.InvariantCulture); - -#if HAVE_BIG_INTEGER - private static string ToStringInternal(BigInteger value) - { - return value.ToString(null, CultureInfo.InvariantCulture); - } -#endif - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - - public static string ToString(ulong value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(float value) => EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); - - internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) => EnsureFloatFormat( - value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); - - private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) - { - if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value))) return text; - - if (floatFormatHandling == FloatFormatHandling.DefaultValue) return !nullable ? "0.0" : Null; - - return quoteChar + text + quoteChar; - } - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(double value) => EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); - - internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) => EnsureFloatFormat( - value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); - - private static string EnsureDecimalPlace(double value, string text) - { - if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 - || text.IndexOf('e') != -1) return text; - - return text + ".0"; - } - - private static string EnsureDecimalPlace(string text) - { - if (text.IndexOf('.') != -1) return text; - - return text + ".0"; - } - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(byte value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - - public static string ToString(sbyte value) => value.ToString(null, CultureInfo.InvariantCulture); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(decimal value) => EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(Guid value) => ToString(value, '"'); - - internal static string ToString(Guid value, char quoteChar) - { - string text; - string qc; -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - text = value.ToString("D", CultureInfo.InvariantCulture); - qc = quoteChar.ToString(CultureInfo.InvariantCulture); -#else - text = value.ToString("D"); - qc = quoteChar.ToString(); -#endif - - return qc + text + qc; - } - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(TimeSpan value) => ToString(value, '"'); - - internal static string ToString(TimeSpan value, char quoteChar) => ToString(value.ToString(), quoteChar); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(Uri? value) - { - if (value == null) return Null; - - return ToString(value, '"'); - } - - internal static string ToString(Uri value, char quoteChar) => ToString(value.OriginalString, quoteChar); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(string? value) => ToString(value, '"'); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// The string delimiter character. - /// A JSON string representation of the . - public static string ToString(string? value, char delimiter) => ToString(value, delimiter, StringEscapeHandling.Default); - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// The string delimiter character. - /// The string escape handling. - /// A JSON string representation of the . - public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) - { - if (delimiter != '"' && delimiter != '\'') throw new ArgumentException("Delimiter must be a single or double quote.", nameof(delimiter)); - - return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, true, stringEscapeHandling); - } - - /// - /// Converts the to its JSON string representation. - /// - /// The value to convert. - /// A JSON string representation of the . - public static string ToString(object? value) - { - if (value == null) return Null; - - var typeCode = ConvertUtils.GetTypeCode(value.GetType()); - - switch (typeCode) - { - case PrimitiveTypeCode.String: - return ToString((string)value); - case PrimitiveTypeCode.Char: - return ToString((char)value); - case PrimitiveTypeCode.Boolean: - return ToString((bool)value); - case PrimitiveTypeCode.SByte: - return ToString((sbyte)value); - case PrimitiveTypeCode.Int16: - return ToString((short)value); - case PrimitiveTypeCode.UInt16: - return ToString((ushort)value); - case PrimitiveTypeCode.Int32: - return ToString((int)value); - case PrimitiveTypeCode.Byte: - return ToString((byte)value); - case PrimitiveTypeCode.UInt32: - return ToString((uint)value); - case PrimitiveTypeCode.Int64: - return ToString((long)value); - case PrimitiveTypeCode.UInt64: - return ToString((ulong)value); - case PrimitiveTypeCode.Single: - return ToString((float)value); - case PrimitiveTypeCode.Double: - return ToString((double)value); - case PrimitiveTypeCode.DateTime: - return ToString((DateTime)value); - case PrimitiveTypeCode.Decimal: - return ToString((decimal)value); -#if HAVE_DB_NULL_TYPE_CODE - case PrimitiveTypeCode.DBNull: - return Null; -#endif -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: - return ToString((DateTimeOffset)value); -#endif - case PrimitiveTypeCode.Guid: - return ToString((Guid)value); - case PrimitiveTypeCode.Uri: - return ToString((Uri)value); - case PrimitiveTypeCode.TimeSpan: - return ToString((TimeSpan)value); -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigInteger: - return ToStringInternal((BigInteger)value); -#endif - } - - throw new ArgumentException( - "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith( - CultureInfo.InvariantCulture, value.GetType())); - } - - #region Serialize - - /// - /// Serializes the specified object to a JSON string. - /// - /// The object to serialize. - /// A JSON string representation of the object. - [DebuggerStepThrough] - public static string SerializeObject(object? value) => SerializeObject(value, null, (JsonSerializerSettings?)null); - - /// - /// Serializes the specified object to a JSON string using formatting. - /// - /// The object to serialize. - /// Indicates how the output should be formatted. - /// - /// A JSON string representation of the object. - /// - [DebuggerStepThrough] - public static string SerializeObject(object? value, Formatting formatting) => - SerializeObject(value, formatting, (JsonSerializerSettings?)null); - - /// - /// Serializes the specified object to a JSON string using a collection of . - /// - /// The object to serialize. - /// A collection of converters used while serializing. - /// A JSON string representation of the object. - [DebuggerStepThrough] - public static string SerializeObject(object? value, params JsonConverter[] converters) - { - var settings = converters != null && converters.Length > 0 - ? new JsonSerializerSettings { Converters = converters } - : null; - - return SerializeObject(value, null, settings); - } - - /// - /// Serializes the specified object to a JSON string using formatting and a collection of . - /// - /// The object to serialize. - /// Indicates how the output should be formatted. - /// A collection of converters used while serializing. - /// A JSON string representation of the object. - [DebuggerStepThrough] - public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) - { - var settings = converters != null && converters.Length > 0 - ? new JsonSerializerSettings { Converters = converters } - : null; - - return SerializeObject(value, null, formatting, settings); - } - - /// - /// Serializes the specified object to a JSON string using . - /// - /// The object to serialize. - /// - /// The used to serialize the object. - /// If this is null, default serialization settings will be used. - /// - /// - /// A JSON string representation of the object. - /// - [DebuggerStepThrough] - public static string SerializeObject(object? value, JsonSerializerSettings? settings) => SerializeObject(value, null, settings); - - /// - /// Serializes the specified object to a JSON string using a type, formatting and . - /// - /// The object to serialize. - /// - /// The used to serialize the object. - /// If this is null, default serialization settings will be used. - /// - /// - /// The type of the value being serialized. - /// This parameter is used when is to - /// write out the type name if the type of the value does not match. - /// Specifying the type is optional. - /// - /// - /// A JSON string representation of the object. - /// - [DebuggerStepThrough] - public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) - { - var jsonSerializer = JsonSerializer.CreateDefault(settings); - - return SerializeObjectInternal(value, type, jsonSerializer); - } - - /// - /// Serializes the specified object to a JSON string using formatting and . - /// - /// The object to serialize. - /// Indicates how the output should be formatted. - /// - /// The used to serialize the object. - /// If this is null, default serialization settings will be used. - /// - /// - /// A JSON string representation of the object. - /// - [DebuggerStepThrough] - public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) => - SerializeObject(value, null, formatting, settings); - - /// - /// Serializes the specified object to a JSON string using a type, formatting and . - /// - /// The object to serialize. - /// Indicates how the output should be formatted. - /// - /// The used to serialize the object. - /// If this is null, default serialization settings will be used. - /// - /// - /// The type of the value being serialized. - /// This parameter is used when is to - /// write out the type name if the type of the value does not match. - /// Specifying the type is optional. - /// - /// - /// A JSON string representation of the object. - /// - [DebuggerStepThrough] - public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) - { - var jsonSerializer = JsonSerializer.CreateDefault(settings); - jsonSerializer.Formatting = formatting; - - return SerializeObjectInternal(value, type, jsonSerializer); - } - - private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) - { - var sb = new StringBuilder(256); - var sw = new StringWriter(sb, CultureInfo.InvariantCulture); - using (var jsonWriter = new JsonTextWriter(sw)) - { - jsonWriter.Formatting = jsonSerializer.Formatting; - - jsonSerializer.Serialize(jsonWriter, value, type); - } - - return sw.ToString(); - } - - #endregion - - #region Deserialize - - /// - /// Deserializes the JSON to a .NET object. - /// - /// The JSON to deserialize. - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static object? DeserializeObject(string value) => DeserializeObject(value, null, (JsonSerializerSettings?)null); - - /// - /// Deserializes the JSON to a .NET object using . - /// - /// The JSON to deserialize. - /// - /// The used to deserialize the object. - /// If this is null, default serialization settings will be used. - /// - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static object? DeserializeObject(string value, JsonSerializerSettings settings) => DeserializeObject(value, null, settings); - - /// - /// Deserializes the JSON to the specified .NET type. - /// - /// The JSON to deserialize. - /// The of object being deserialized. - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static object? DeserializeObject(string value, Type type) => DeserializeObject(value, type, (JsonSerializerSettings?)null); - - /// - /// Deserializes the JSON to the specified .NET type. - /// - /// The type of the object to deserialize to. - /// The JSON to deserialize. - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static T? DeserializeObject(string value) => DeserializeObject(value, (JsonSerializerSettings?)null); - - /// - /// Deserializes the JSON to the given anonymous type. - /// - /// - /// The anonymous type to deserialize to. This can't be specified - /// traditionally and must be inferred from the anonymous type passed - /// as a parameter. - /// - /// The JSON to deserialize. - /// The anonymous type object. - /// The deserialized anonymous type from the JSON string. - [DebuggerStepThrough] - public static T? DeserializeAnonymousType(string value, T anonymousTypeObject) => DeserializeObject(value); - - /// - /// Deserializes the JSON to the given anonymous type using . - /// - /// - /// The anonymous type to deserialize to. This can't be specified - /// traditionally and must be inferred from the anonymous type passed - /// as a parameter. - /// - /// The JSON to deserialize. - /// The anonymous type object. - /// - /// The used to deserialize the object. - /// If this is null, default serialization settings will be used. - /// - /// The deserialized anonymous type from the JSON string. - [DebuggerStepThrough] - public static T? DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings) => - DeserializeObject(value, settings); - - /// - /// Deserializes the JSON to the specified .NET type using a collection of . - /// - /// The type of the object to deserialize to. - /// The JSON to deserialize. - /// Converters to use while deserializing. - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static T? DeserializeObject(string value, params JsonConverter[] converters) => (T?)DeserializeObject(value, typeof(T), converters); - - /// - /// Deserializes the JSON to the specified .NET type using . - /// - /// The type of the object to deserialize to. - /// The object to deserialize. - /// - /// The used to deserialize the object. - /// If this is null, default serialization settings will be used. - /// - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static T? DeserializeObject(string value, JsonSerializerSettings? settings) => (T?)DeserializeObject(value, typeof(T), settings); - - /// - /// Deserializes the JSON to the specified .NET type using a collection of . - /// - /// The JSON to deserialize. - /// The type of the object to deserialize. - /// Converters to use while deserializing. - /// The deserialized object from the JSON string. - [DebuggerStepThrough] - public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) - { - var settings = converters != null && converters.Length > 0 - ? new JsonSerializerSettings { Converters = converters } - : null; - - return DeserializeObject(value, type, settings); - } - - /// - /// Deserializes the JSON to the specified .NET type using . - /// - /// The JSON to deserialize. - /// The type of the object to deserialize to. - /// - /// The used to deserialize the object. - /// If this is null, default serialization settings will be used. - /// - /// The deserialized object from the JSON string. - public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - var jsonSerializer = JsonSerializer.CreateDefault(settings); - - // by default DeserializeObject should check for additional content - if (!jsonSerializer.IsCheckAdditionalContentSet()) jsonSerializer.CheckAdditionalContent = true; - - using (var reader = new JsonTextReader(new StringReader(value))) return jsonSerializer.Deserialize(reader, type); - } - - #endregion - - #region Populate - - /// - /// Populates the object with values from the JSON string. - /// - /// The JSON to populate values from. - /// The target object to populate values onto. - [DebuggerStepThrough] - public static void PopulateObject(string value, object target) => PopulateObject(value, target, null); - - /// - /// Populates the object with values from the JSON string using . - /// - /// The JSON to populate values from. - /// The target object to populate values onto. - /// - /// The used to deserialize the object. - /// If this is null, default serialization settings will be used. - /// - public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) - { - var jsonSerializer = JsonSerializer.CreateDefault(settings); - - using (JsonReader jsonReader = new JsonTextReader(new StringReader(value))) - { - jsonSerializer.Populate(jsonReader, target); - - if (settings != null && settings.CheckAdditionalContent) - { - while (jsonReader.Read()) - { - if (jsonReader.TokenType != JsonToken.Comment) - throw JsonSerializationException.Create(jsonReader, - "Additional text found in JSON string after finishing deserializing object."); - } - } - } - } - - #endregion - - #region Xml - -#if HAVE_XML_DOCUMENT - /// - /// Serializes the to a JSON string. - /// - /// The node to serialize. - /// A JSON string of the . - public static string SerializeXmlNode(XmlNode? node) - { - return SerializeXmlNode(node, Formatting.None); - } - - /// - /// Serializes the to a JSON string using formatting. - /// - /// The node to serialize. - /// Indicates how the output should be formatted. - /// A JSON string of the . - public static string SerializeXmlNode(XmlNode? node, Formatting formatting) - { - XmlNodeConverter converter = new XmlNodeConverter(); - - return SerializeObject(node, formatting, converter); - } - - /// - /// Serializes the to a JSON string using formatting and omits the root object if is true. - /// - /// The node to serialize. - /// Indicates how the output should be formatted. - /// Omits writing the root object. - /// A JSON string of the . - public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) - { - XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; - - return SerializeObject(node, formatting, converter); - } - - /// - /// Deserializes the from a JSON string. - /// - /// The JSON string. - /// The deserialized . - public static XmlDocument? DeserializeXmlNode(string value) - { - return DeserializeXmlNode(value, null); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by . - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// The deserialized . - public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) - { - return DeserializeXmlNode(value, deserializeRootElementName, false); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by - /// and writes a Json.NET array attribute for collections. - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// - /// A value to indicate whether to write the Json.NET array attribute. - /// This attribute helps preserve arrays when converting the written XML back to JSON. - /// - /// The deserialized . - public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) - { - return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, false); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by , - /// writes a Json.NET array attribute for collections, and encodes special characters. - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// - /// A value to indicate whether to write the Json.NET array attribute. - /// This attribute helps preserve arrays when converting the written XML back to JSON. - /// - /// - /// A value to indicate whether to encode special characters when converting JSON to XML. - /// If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify - /// XML namespaces, attributes or processing directives. Instead special characters are encoded and written - /// as part of the XML element name. - /// - /// The deserialized . - public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) - { - XmlNodeConverter converter = new XmlNodeConverter(); - converter.DeserializeRootElementName = deserializeRootElementName; - converter.WriteArrayAttribute = writeArrayAttribute; - converter.EncodeSpecialCharacters = encodeSpecialCharacters; - - return (XmlDocument?)DeserializeObject(value, typeof(XmlDocument), converter); - } -#endif - -#if HAVE_XLINQ - /// - /// Serializes the to a JSON string. - /// - /// The node to convert to JSON. - /// A JSON string of the . - public static string SerializeXNode(XObject? node) - { - return SerializeXNode(node, Formatting.None); - } - - /// - /// Serializes the to a JSON string using formatting. - /// - /// The node to convert to JSON. - /// Indicates how the output should be formatted. - /// A JSON string of the . - public static string SerializeXNode(XObject? node, Formatting formatting) - { - return SerializeXNode(node, formatting, false); - } - - /// - /// Serializes the to a JSON string using formatting and omits the root object if is true. - /// - /// The node to serialize. - /// Indicates how the output should be formatted. - /// Omits writing the root object. - /// A JSON string of the . - public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) - { - XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; - - return SerializeObject(node, formatting, converter); - } - - /// - /// Deserializes the from a JSON string. - /// - /// The JSON string. - /// The deserialized . - public static XDocument? DeserializeXNode(string value) - { - return DeserializeXNode(value, null); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by . - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// The deserialized . - public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) - { - return DeserializeXNode(value, deserializeRootElementName, false); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by - /// and writes a Json.NET array attribute for collections. - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// - /// A value to indicate whether to write the Json.NET array attribute. - /// This attribute helps preserve arrays when converting the written XML back to JSON. - /// - /// The deserialized . - public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) - { - return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, false); - } - - /// - /// Deserializes the from a JSON string nested in a root element specified by , - /// writes a Json.NET array attribute for collections, and encodes special characters. - /// - /// The JSON string. - /// The name of the root element to append when deserializing. - /// - /// A value to indicate whether to write the Json.NET array attribute. - /// This attribute helps preserve arrays when converting the written XML back to JSON. - /// - /// - /// A value to indicate whether to encode special characters when converting JSON to XML. - /// If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify - /// XML namespaces, attributes or processing directives. Instead special characters are encoded and written - /// as part of the XML element name. - /// - /// The deserialized . - public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) - { - XmlNodeConverter converter = new XmlNodeConverter(); - converter.DeserializeRootElementName = deserializeRootElementName; - converter.WriteArrayAttribute = writeArrayAttribute; - converter.EncodeSpecialCharacters = encodeSpecialCharacters; - - return (XDocument?)DeserializeObject(value, typeof(XDocument), converter); - } -#endif - - #endregion - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverter.cs deleted file mode 100644 index c4f6ec073..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverter.cs +++ /dev/null @@ -1,151 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Converts an object to and from JSON. - /// - internal abstract class JsonConverter - { - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public abstract bool CanConvert(Type objectType); - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); - - /// - /// Gets a value indicating whether this can read JSON. - /// - /// true if this can read JSON; otherwise, false. - public virtual bool CanRead => true; - - /// - /// Gets a value indicating whether this can write JSON. - /// - /// true if this can write JSON; otherwise, false. - public virtual bool CanWrite => true; - } - - /// - /// Converts an object to and from JSON. - /// - /// The object type to convert. - internal abstract class JsonConverter : JsonConverter - { - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// - /// The existing value of object being read. If there is no existing value then null - /// will be used. - /// - /// The existing value has a value. - /// The calling serializer. - /// The object value. - public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (!(value != null ? value is T : ReflectionUtils.IsNullable(typeof(T)))) - throw new JsonSerializationException( - "Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); - - WriteJson(writer, (T?)value, serializer); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var existingIsNull = existingValue == null; - if (!(existingIsNull || existingValue is T)) - throw new JsonSerializationException( - "Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, - typeof(T))); - - return ReadJson(reader, objectType, existingIsNull ? default : (T?)existingValue, !existingIsNull, serializer); - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public sealed override bool CanConvert(Type objectType) => typeof(T).IsAssignableFrom(objectType); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterAttribute.cs deleted file mode 100644 index 13e68da0b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterAttribute.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the to use the specified when serializing the - /// member or class. - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface - | AttributeTargets.Enum | AttributeTargets.Parameter)] - internal sealed class JsonConverterAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// Type of the . - public JsonConverterAttribute(Type converterType) - { - if (converterType == null) throw new ArgumentNullException(nameof(converterType)); - - ConverterType = converterType; - } - - /// - /// Initializes a new instance of the class. - /// - /// Type of the . - /// - /// Parameter list to use when constructing the . Can be - /// null. - /// - public JsonConverterAttribute(Type converterType, params object[] converterParameters) - : this(converterType) => - ConverterParameters = converterParameters; - - /// - /// The parameter list to use when constructing the described by . - /// If null, the default constructor is used. - /// - public object[]? ConverterParameters { get; } - - /// - /// Gets the of the . - /// - /// The of the . - public Type ConverterType { get; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterCollection.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterCollection.cs deleted file mode 100644 index 6d0205cfd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonConverterCollection.cs +++ /dev/null @@ -1,37 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Collections.ObjectModel; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Represents a collection of . - /// - internal class JsonConverterCollection : Collection { } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonDictionaryAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonDictionaryAttribute.cs deleted file mode 100644 index 021133dc9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonDictionaryAttribute.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the how to serialize the collection. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] - internal sealed class JsonDictionaryAttribute : JsonContainerAttribute - { - /// - /// Initializes a new instance of the class. - /// - public JsonDictionaryAttribute() { } - - /// - /// Initializes a new instance of the class with the specified container Id. - /// - /// The container Id. - public JsonDictionaryAttribute(string id) - : base(id) { } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonException.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonException.cs deleted file mode 100644 index c0548f1c2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonException.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// The exception thrown when an error occurs during JSON serialization or deserialization. - /// -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - [Serializable] -#endif - internal class JsonException : Exception - { - /// - /// Initializes a new instance of the class. - /// - public JsonException() { } - - /// - /// Initializes a new instance of the class - /// with a specified error message. - /// - /// The error message that explains the reason for the exception. - public JsonException(string message) - : base(message) { } - - /// - /// Initializes a new instance of the class - /// with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonException(string message, Exception? innerException) - : base(message, innerException) { } - -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// The parameter is null. - /// The class name is null or is zero (0). - public JsonException(SerializationInfo info, StreamingContext context) -#pragma warning disable SYSLIB0051 - : base(info, context) -#pragma warning restore SYSLIB0051 - { - } -#endif - - internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) - { - message = JsonPosition.FormatMessage(lineInfo, path, message); - - return new JsonException(message); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonExtensionDataAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonExtensionDataAttribute.cs deleted file mode 100644 index b091dfd36..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonExtensionDataAttribute.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the to deserialize properties with no matching class member into the specified - /// collection - /// and write values during serialization. - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - internal class JsonExtensionDataAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - public JsonExtensionDataAttribute() - { - WriteData = true; - ReadData = true; - } - - /// - /// Gets or sets a value that indicates whether to read extension data when deserializing the object. - /// - /// - /// true to read extension data when deserializing the object; otherwise, false. The default is true. - /// - public bool ReadData { get; set; } - - /// - /// Gets or sets a value that indicates whether to write extension data when serializing the object. - /// - /// - /// true to write extension data when serializing the object; otherwise, false. The default is true. - /// - public bool WriteData { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonIgnoreAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonIgnoreAttribute.cs deleted file mode 100644 index a9fce7195..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonIgnoreAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the not to serialize the public field or public read/write property value. - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - internal sealed class JsonIgnoreAttribute : Attribute { } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonNameTable.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonNameTable.cs deleted file mode 100644 index 0a45e1203..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonNameTable.cs +++ /dev/null @@ -1,18 +0,0 @@ -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Base class for a table of atomized string objects. - /// - internal abstract class JsonNameTable - { - /// - /// Gets a string containing the same characters as the specified range of characters in the given array. - /// - /// The character array containing the name to find. - /// The zero-based index into the array specifying the first character of the name. - /// The number of characters in the name. - /// A string containing the same characters as the specified range of characters in the given array. - public abstract string? Get(char[] key, int start, int length); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonObjectAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonObjectAttribute.cs deleted file mode 100644 index 832766bb0..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonObjectAttribute.cs +++ /dev/null @@ -1,102 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the how to serialize the object. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] - internal sealed class JsonObjectAttribute : JsonContainerAttribute - { - /// - /// Initializes a new instance of the class. - /// - public JsonObjectAttribute() { } - - /// - /// Initializes a new instance of the class with the specified member serialization. - /// - /// The member serialization. - public JsonObjectAttribute(MemberSerialization memberSerialization) => MemberSerialization = memberSerialization; - - /// - /// Initializes a new instance of the class with the specified container Id. - /// - /// The container Id. - public JsonObjectAttribute(string id) - : base(id) { } - - internal NullValueHandling? _itemNullValueHandling; - - // yuck. can't set nullable properties on an attribute in C# - // have to use this approach to get an unset default state - internal Required? _itemRequired; - internal MissingMemberHandling? _missingMemberHandling; - - /// - /// Gets or sets how the object's properties with null values are handled during serialization and deserialization. - /// - /// How the object's properties with null values are handled during serialization and deserialization. - public NullValueHandling ItemNullValueHandling - { - get => _itemNullValueHandling ?? default; - set => _itemNullValueHandling = value; - } - - /// - /// Gets or sets a value that indicates whether the object's properties are required. - /// - /// - /// A value indicating whether the object's properties are required. - /// - public Required ItemRequired - { - get => _itemRequired ?? default; - set => _itemRequired = value; - } - - /// - /// Gets or sets the member serialization. - /// - /// The member serialization. - public MemberSerialization MemberSerialization { get; set; } = MemberSerialization.OptOut; - - /// - /// Gets or sets the missing member handling used when deserializing this object. - /// - /// The missing member handling. - public MissingMemberHandling MissingMemberHandling - { - get => _missingMemberHandling ?? default; - set => _missingMemberHandling = value; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPosition.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPosition.cs deleted file mode 100644 index 21d51d58b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPosition.cs +++ /dev/null @@ -1,158 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal enum JsonContainerType - { - None = 0, - Object = 1, - Array = 2, - Constructor = 3 - } - - internal struct JsonPosition - { - private static readonly char[] SpecialCharacters = - { - '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' - }; - - internal JsonContainerType Type; - internal int Position; - internal string? PropertyName; - internal bool HasIndex; - - public JsonPosition(JsonContainerType type) - { - Type = type; - HasIndex = TypeHasIndex(type); - Position = -1; - PropertyName = null; - } - - internal int CalculateLength() - { - switch (Type) - { - case JsonContainerType.Object: - return PropertyName!.Length + 5; - case JsonContainerType.Array: - case JsonContainerType.Constructor: - return MathUtils.IntLength((ulong)Position) + 2; - default: - throw new ArgumentOutOfRangeException(nameof(Type)); - } - } - - internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) - { - switch (Type) - { - case JsonContainerType.Object: - var propertyName = PropertyName!; - if (propertyName.IndexOfAny(SpecialCharacters) != -1) - { - sb.Append(@"['"); - - if (writer == null) writer = new StringWriter(sb); - - JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', false, JavaScriptUtils.SingleQuoteCharEscapeFlags, - StringEscapeHandling.Default, null, ref buffer); - - sb.Append(@"']"); - } - else - { - if (sb.Length > 0) sb.Append('.'); - - sb.Append(propertyName); - } - break; - case JsonContainerType.Array: - case JsonContainerType.Constructor: - sb.Append('['); - sb.Append(Position); - sb.Append(']'); - break; - } - } - - internal static bool TypeHasIndex(JsonContainerType type) => type == JsonContainerType.Array || type == JsonContainerType.Constructor; - - internal static string BuildPath(List positions, JsonPosition? currentPosition) - { - var capacity = 0; - if (positions != null) - { - for (var i = 0; i < positions.Count; i++) capacity += positions[i].CalculateLength(); - } - if (currentPosition != null) capacity += currentPosition.GetValueOrDefault().CalculateLength(); - - var sb = new StringBuilder(capacity); - StringWriter? writer = null; - char[]? buffer = null; - if (positions != null) - { - foreach (var state in positions) state.WriteTo(sb, ref writer, ref buffer); - } - if (currentPosition != null) currentPosition.GetValueOrDefault().WriteTo(sb, ref writer, ref buffer); - - return sb.ToString(); - } - - internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) - { - // don't add a fullstop and space when message ends with a new line - if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) - { - message = message.Trim(); - - if (!message.EndsWith('.')) message += "."; - - message += " "; - } - - message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); - - if (lineInfo != null && lineInfo.HasLineInfo()) - message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); - - message += "."; - - return message; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPropertyAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPropertyAttribute.cs deleted file mode 100644 index 5bd230044..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonPropertyAttribute.cs +++ /dev/null @@ -1,227 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the to always serialize the member with the specified name. - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)] - internal sealed class JsonPropertyAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - public JsonPropertyAttribute() { } - - /// - /// Initializes a new instance of the class with the specified name. - /// - /// Name of the property. - public JsonPropertyAttribute(string propertyName) => PropertyName = propertyName; - - internal DefaultValueHandling? _defaultValueHandling; - internal bool? _isReference; - internal bool? _itemIsReference; - internal ReferenceLoopHandling? _itemReferenceLoopHandling; - - internal TypeNameHandling? _itemTypeNameHandling; - - // yuck. can't set nullable properties on an attribute in C# - // have to use this approach to get an unset default state - internal NullValueHandling? _nullValueHandling; - internal ObjectCreationHandling? _objectCreationHandling; - internal int? _order; - internal ReferenceLoopHandling? _referenceLoopHandling; - internal Required? _required; - internal TypeNameHandling? _typeNameHandling; - - /// - /// Gets or sets the default value handling used when serializing this property. - /// - /// The default value handling. - public DefaultValueHandling DefaultValueHandling - { - get => _defaultValueHandling ?? default; - set => _defaultValueHandling = value; - } - - /// - /// Gets or sets whether this property's value is serialized as a reference. - /// - /// Whether this property's value is serialized as a reference. - public bool IsReference - { - get => _isReference ?? default; - set => _isReference = value; - } - - /// - /// The parameter list to use when constructing the described by - /// . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the that exactly matches the - /// number, - /// order, and type of these parameters. - /// - /// - /// - /// [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] - /// - /// - public object[]? ItemConverterParameters { get; set; } - - /// - /// Gets or sets the type used when serializing the property's collection items. - /// - /// The collection's items type. - public Type? ItemConverterType { get; set; } - - /// - /// Gets or sets whether this property's collection items are serialized as a reference. - /// - /// Whether this property's collection items are serialized as a reference. - public bool ItemIsReference - { - get => _itemIsReference ?? default; - set => _itemIsReference = value; - } - - /// - /// Gets or sets the reference loop handling used when serializing the property's collection items. - /// - /// The collection's items reference loop handling. - public ReferenceLoopHandling ItemReferenceLoopHandling - { - get => _itemReferenceLoopHandling ?? default; - set => _itemReferenceLoopHandling = value; - } - - /// - /// Gets or sets the type name handling used when serializing the property's collection items. - /// - /// The collection's items type name handling. - public TypeNameHandling ItemTypeNameHandling - { - get => _itemTypeNameHandling ?? default; - set => _itemTypeNameHandling = value; - } - - /// - /// The parameter list to use when constructing the described by - /// . - /// If null, the default constructor is used. - /// When non-null, there must be a constructor defined in the that exactly matches the - /// number, - /// order, and type of these parameters. - /// - /// - /// - /// [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] - /// - /// - public object[]? NamingStrategyParameters { get; set; } - - /// - /// Gets or sets the of the . - /// - /// The of the . - public Type? NamingStrategyType { get; set; } - - /// - /// Gets or sets the null value handling used when serializing this property. - /// - /// The null value handling. - public NullValueHandling NullValueHandling - { - get => _nullValueHandling ?? default; - set => _nullValueHandling = value; - } - - /// - /// Gets or sets the object creation handling used when deserializing this property. - /// - /// The object creation handling. - public ObjectCreationHandling ObjectCreationHandling - { - get => _objectCreationHandling ?? default; - set => _objectCreationHandling = value; - } - - /// - /// Gets or sets the order of serialization of a member. - /// - /// The numeric order of serialization. - public int Order - { - get => _order ?? default; - set => _order = value; - } - - /// - /// Gets or sets the name of the property. - /// - /// The name of the property. - public string? PropertyName { get; set; } - - /// - /// Gets or sets the reference loop handling used when serializing this property. - /// - /// The reference loop handling. - public ReferenceLoopHandling ReferenceLoopHandling - { - get => _referenceLoopHandling ?? default; - set => _referenceLoopHandling = value; - } - - /// - /// Gets or sets a value indicating whether this property is required. - /// - /// - /// A value indicating whether this property is required. - /// - public Required Required - { - get => _required ?? Required.Default; - set => _required = value; - } - - /// - /// Gets or sets the type name handling used when serializing this property. - /// - /// The type name handling. - public TypeNameHandling TypeNameHandling - { - get => _typeNameHandling ?? default; - set => _typeNameHandling = value; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.Async.cs deleted file mode 100644 index 3303ed22a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.Async.cs +++ /dev/null @@ -1,248 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal abstract partial class JsonReader - { - /// - /// Asynchronously reads the next JSON token from the source. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns true if the next token was read successfully; false if there are no more tokens to read. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Read().ToAsync(); - } - - /// - /// Asynchronously skips the children of the current token. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public async Task SkipAsync(CancellationToken cancellationToken = default) - { - if (TokenType == JsonToken.PropertyName) - { - await ReadAsync(cancellationToken).ConfigureAwait(false); - } - - if (JsonTokenUtils.IsStartToken(TokenType)) - { - int depth = Depth; - - while (await ReadAsync(cancellationToken).ConfigureAwait(false) && depth < Depth) - { - } - } - } - - internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) - { - if (!await ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw CreateUnexpectedEndException(); - } - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsBooleanAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBoolean()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a []. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the []. This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsBytesAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBytes()); - } - - internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) - { - List buffer = new List(); - - while (true) - { - if (!await ReadAsync(cancellationToken).ConfigureAwait(false)) - { - SetToken(JsonToken.None); - } - - if (ReadArrayElementIntoByteArrayReportDone(buffer)) - { - byte[] d = buffer.ToArray(); - SetToken(JsonToken.Bytes, d, false); - return d; - } - } - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTime()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTimeOffset()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsDecimalAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDecimal()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsDoubleAsync(CancellationToken cancellationToken = default) - { - return Task.FromResult(ReadAsDouble()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsInt32Async(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsInt32()); - } - - /// - /// Asynchronously reads the next JSON token from the source as a . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the . This result will be null at the end of an array. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsStringAsync(CancellationToken cancellationToken = default) - { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsString()); - } - - internal async Task ReadAndMoveToContentAsync(CancellationToken cancellationToken) - { - return await ReadAsync(cancellationToken).ConfigureAwait(false) && await MoveToContentAsync(cancellationToken).ConfigureAwait(false); - } - - internal Task MoveToContentAsync(CancellationToken cancellationToken) - { - switch (TokenType) - { - case JsonToken.None: - case JsonToken.Comment: - return MoveToContentFromNonContentAsync(cancellationToken); - default: - return AsyncUtils.True; - } - } - - private async Task MoveToContentFromNonContentAsync(CancellationToken cancellationToken) - { - while (true) - { - if (!await ReadAsync(cancellationToken).ConfigureAwait(false)) - { - return false; - } - - switch (TokenType) - { - case JsonToken.None: - case JsonToken.Comment: - break; - default: - return true; - } - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.cs deleted file mode 100644 index 7590547ad..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReader.cs +++ /dev/null @@ -1,1179 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. - /// - internal abstract partial class JsonReader : IDisposable - { - /// - /// Specifies the state of the reader. - /// - protected internal enum State - { - /// - /// A read method has not been called. - /// - Start, - - /// - /// The end of the file has been reached successfully. - /// - Complete, - - /// - /// Reader is at a property. - /// - Property, - - /// - /// Reader is at the start of an object. - /// - ObjectStart, - - /// - /// Reader is in an object. - /// - Object, - - /// - /// Reader is at the start of an array. - /// - ArrayStart, - - /// - /// Reader is in an array. - /// - Array, - - /// - /// The method has been called. - /// - Closed, - - /// - /// Reader has just read a value. - /// - PostValue, - - /// - /// Reader is at the start of a constructor. - /// - ConstructorStart, - - /// - /// Reader is in a constructor. - /// - Constructor, - - /// - /// An error occurred that prevents the read operation from continuing. - /// - Error, - - /// - /// The end of the file has been reached successfully. - /// - Finished - } - - // current Token data - private JsonToken _tokenType; - private object? _value; - internal char _quoteChar; - internal State _currentState; - private JsonPosition _currentPosition; - private CultureInfo? _culture; - private DateTimeZoneHandling _dateTimeZoneHandling; - private int? _maxDepth; - private bool _hasExceededMaxDepth; - internal DateParseHandling _dateParseHandling; - internal FloatParseHandling _floatParseHandling; - private List? _stack; - - /// - /// Gets the current reader state. - /// - /// The current reader state. - protected State CurrentState => _currentState; - - /// - /// Gets or sets a value indicating whether the source should be closed when this reader is closed. - /// - /// - /// true to close the source when this reader is closed; otherwise false. The default is true. - /// - public bool CloseInput { get; set; } - - /// - /// Gets or sets a value indicating whether multiple pieces of JSON content can - /// be read from a continuous stream without erroring. - /// - /// - /// true to support reading multiple pieces of JSON content; otherwise false. - /// The default is false. - /// - public bool SupportMultipleContent { get; set; } - - /// - /// Gets the quotation mark character used to enclose the value of a string. - /// - public virtual char QuoteChar - { - get => _quoteChar; - protected internal set => _quoteChar = value; - } - - /// - /// Gets or sets how time zones are handled when reading JSON. - /// - public DateTimeZoneHandling DateTimeZoneHandling - { - get => _dateTimeZoneHandling; - set - { - if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) - throw new ArgumentOutOfRangeException(nameof(value)); - - _dateTimeZoneHandling = value; - } - } - - /// - /// Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when - /// reading JSON. - /// - public DateParseHandling DateParseHandling - { - get => _dateParseHandling; - set - { - if (value < DateParseHandling.None || -#if HAVE_DATE_TIME_OFFSET - value > DateParseHandling.DateTimeOffset -#else - value > DateParseHandling.DateTime -#endif - ) - throw new ArgumentOutOfRangeException(nameof(value)); - - _dateParseHandling = value; - } - } - - /// - /// Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. - /// - public FloatParseHandling FloatParseHandling - { - get => _floatParseHandling; - set - { - if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) throw new ArgumentOutOfRangeException(nameof(value)); - - _floatParseHandling = value; - } - } - - /// - /// Gets or sets how custom date formatted strings are parsed when reading JSON. - /// - public string? DateFormatString { get; set; } - - /// - /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a - /// . - /// A null value means there is no maximum. - /// The default value is 128. - /// - public int? MaxDepth - { - get => _maxDepth; - set - { - if (value <= 0) throw new ArgumentException("Value must be positive.", nameof(value)); - - _maxDepth = value; - } - } - - /// - /// Gets the type of the current JSON token. - /// - public virtual JsonToken TokenType => _tokenType; - - /// - /// Gets the text value of the current JSON token. - /// - public virtual object? Value => _value; - - /// - /// Gets the .NET type for the current JSON token. - /// - public virtual Type? ValueType => _value?.GetType(); - - /// - /// Gets the depth of the current token in the JSON document. - /// - /// The depth of the current token in the JSON document. - public virtual int Depth - { - get - { - var depth = _stack?.Count ?? 0; - if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) - return depth; - - return depth + 1; - } - } - - /// - /// Gets the path of the current JSON token. - /// - public virtual string Path - { - get - { - if (_currentPosition.Type == JsonContainerType.None) return string.Empty; - - var insideContainer = _currentState != State.ArrayStart - && _currentState != State.ConstructorStart - && _currentState != State.ObjectStart; - - var current = insideContainer ? (JsonPosition?)_currentPosition : null; - - return JsonPosition.BuildPath(_stack!, current); - } - } - - /// - /// Gets or sets the culture used when reading JSON. Defaults to . - /// - public CultureInfo Culture - { - get => _culture ?? CultureInfo.InvariantCulture; - set => _culture = value; - } - - internal JsonPosition GetPosition(int depth) - { - if (_stack != null && depth < _stack.Count) return _stack[depth]; - - return _currentPosition; - } - - /// - /// Initializes a new instance of the class. - /// - protected JsonReader() - { - _currentState = State.Start; - _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; - _dateParseHandling = DateParseHandling.DateTime; - _floatParseHandling = FloatParseHandling.Double; - _maxDepth = 64; - - CloseInput = true; - } - - private void Push(JsonContainerType value) - { - UpdateScopeWithFinishedValue(); - - if (_currentPosition.Type == JsonContainerType.None) - _currentPosition = new JsonPosition(value); - else - { - if (_stack == null) _stack = new List(); - - _stack.Add(_currentPosition); - _currentPosition = new JsonPosition(value); - - // this is a little hacky because Depth increases when first property/value is written but only testing here is faster/simpler - if (_maxDepth != null && Depth + 1 > _maxDepth && !_hasExceededMaxDepth) - { - _hasExceededMaxDepth = true; - throw JsonReaderException.Create(this, - "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); - } - } - } - - private JsonContainerType Pop() - { - JsonPosition oldPosition; - if (_stack != null && _stack.Count > 0) - { - oldPosition = _currentPosition; - _currentPosition = _stack[_stack.Count - 1]; - _stack.RemoveAt(_stack.Count - 1); - } - else - { - oldPosition = _currentPosition; - _currentPosition = new JsonPosition(); - } - - if (_maxDepth != null && Depth <= _maxDepth) _hasExceededMaxDepth = false; - - return oldPosition.Type; - } - - private JsonContainerType Peek() => _currentPosition.Type; - - /// - /// Reads the next JSON token from the source. - /// - /// true if the next token was read successfully; false if there are no more tokens to read. - public abstract bool Read(); - - /// - /// Reads the next JSON token from the source as a of . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public virtual int? ReadAsInt32() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Integer: - case JsonToken.Float: - var v = Value!; - if (v is int i) return i; - -#if HAVE_BIG_INTEGER - if (v is BigInteger value) - { - i = (int)value; - } - else -#endif - { - try - { - i = Convert.ToInt32(v, CultureInfo.InvariantCulture); - } - catch (Exception ex) - { - // handle error for large integer overflow exceptions - throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, v), ex); - } - } - - SetToken(JsonToken.Integer, i, false); - return i; - case JsonToken.String: - var s = (string?)Value; - return ReadInt32String(s); - } - - throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - internal int? ReadInt32String(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (int.TryParse(s, NumberStyles.Integer, Culture, out var i)) - { - SetToken(JsonToken.Integer, i, false); - return i; - } - SetToken(JsonToken.String, s, false); - throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } - - /// - /// Reads the next JSON token from the source as a . - /// - /// A . This method will return null at the end of an array. - public virtual string? ReadAsString() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.String: - return (string?)Value; - } - - if (JsonTokenUtils.IsPrimitiveToken(t)) - { - var v = Value; - if (v != null) - { - string s; - if (v is IFormattable formattable) - s = formattable.ToString(null, Culture); - else - s = v is Uri uri ? uri.OriginalString : v.ToString(); - - SetToken(JsonToken.String, s, false); - return s; - } - } - - throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - /// - /// Reads the next JSON token from the source as a []. - /// - /// - /// A [] or null if the next JSON token is null. This method will return null at - /// the end of an array. - /// - public virtual byte[]? ReadAsBytes() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.StartObject: - { - ReadIntoWrappedTypeObject(); - - var data = ReadAsBytes(); - ReaderReadAndAssert(); - - if (TokenType != JsonToken.EndObject) - throw JsonReaderException.Create(this, - "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); - - SetToken(JsonToken.Bytes, data, false); - return data; - } - case JsonToken.String: - { - // attempt to convert possible base 64 or GUID string to bytes - // GUID has to have format 00000000-0000-0000-0000-000000000000 - var s = (string)Value!; - - byte[] data; - - if (s.Length == 0) - data = CollectionUtils.ArrayEmpty(); - else if (ConvertUtils.TryConvertGuid(s, out var g1)) - data = g1.ToByteArray(); - else - data = Convert.FromBase64String(s); - - SetToken(JsonToken.Bytes, data, false); - return data; - } - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Bytes: - if (Value is Guid g2) - { - var data = g2.ToByteArray(); - SetToken(JsonToken.Bytes, data, false); - return data; - } - - return (byte[]?)Value; - case JsonToken.StartArray: - return ReadArrayIntoByteArray(); - } - - throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - internal byte[] ReadArrayIntoByteArray() - { - var buffer = new List(); - - while (true) - { - if (!Read()) SetToken(JsonToken.None); - - if (ReadArrayElementIntoByteArrayReportDone(buffer)) - { - var d = buffer.ToArray(); - SetToken(JsonToken.Bytes, d, false); - return d; - } - } - } - - private bool ReadArrayElementIntoByteArrayReportDone(List buffer) - { - switch (TokenType) - { - case JsonToken.None: - throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); - case JsonToken.Integer: - buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); - return false; - case JsonToken.EndArray: - return true; - case JsonToken.Comment: - return false; - default: - throw JsonReaderException.Create(this, - "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); - } - } - - /// - /// Reads the next JSON token from the source as a of . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public virtual double? ReadAsDouble() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Integer: - case JsonToken.Float: - var v = Value!; - if (v is double d) return d; - -#if HAVE_BIG_INTEGER - if (v is BigInteger value) - { - d = (double)value; - } - else -#endif - { - d = Convert.ToDouble(v, CultureInfo.InvariantCulture); - } - - SetToken(JsonToken.Float, d, false); - - return d; - case JsonToken.String: - return ReadDoubleString((string?)Value); - } - - throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - internal double? ReadDoubleString(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var d)) - { - SetToken(JsonToken.Float, d, false); - return d; - } - SetToken(JsonToken.String, s, false); - throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } - - /// - /// Reads the next JSON token from the source as a of . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public virtual bool? ReadAsBoolean() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Integer: - case JsonToken.Float: - bool b; -#if HAVE_BIG_INTEGER - if (Value is BigInteger integer) - { - b = integer != 0; - } - else -#endif - { - b = Convert.ToBoolean(Value, CultureInfo.InvariantCulture); - } - - SetToken(JsonToken.Boolean, b, false); - return b; - case JsonToken.String: - return ReadBooleanString((string?)Value); - case JsonToken.Boolean: - return (bool)Value!; - } - - throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - internal bool? ReadBooleanString(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (bool.TryParse(s, out var b)) - { - SetToken(JsonToken.Boolean, b, false); - return b; - } - SetToken(JsonToken.String, s, false); - throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } - - /// - /// Reads the next JSON token from the source as a of . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public virtual decimal? ReadAsDecimal() - { - var t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Integer: - case JsonToken.Float: - var v = Value!; - - if (v is decimal d) return d; - -#if HAVE_BIG_INTEGER - if (v is BigInteger value) - { - d = (decimal)value; - } - else -#endif - { - try - { - d = Convert.ToDecimal(v, CultureInfo.InvariantCulture); - } - catch (Exception ex) - { - // handle error for large integer overflow exceptions - throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, v), ex); - } - } - - SetToken(JsonToken.Float, d, false); - return d; - case JsonToken.String: - return ReadDecimalString((string?)Value); - } - - throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - - internal decimal? ReadDecimalString(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (decimal.TryParse(s, NumberStyles.Number, Culture, out var d)) - { - SetToken(JsonToken.Float, d, false); - return d; - } - if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out d) == ParseResult.Success) - { - // This is to handle strings like "96.014e-05" that are not supported by traditional decimal.TryParse - SetToken(JsonToken.Float, d, false); - return d; - } - SetToken(JsonToken.String, s, false); - throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } - - /// - /// Reads the next JSON token from the source as a of . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public virtual DateTime? ReadAsDateTime() - { - switch (GetContentToken()) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Date: -#if HAVE_DATE_TIME_OFFSET - if (Value is DateTimeOffset offset) - { - SetToken(JsonToken.Date, offset.DateTime, false); - } -#endif - - return (DateTime)Value!; - case JsonToken.String: - return ReadDateTimeString((string?)Value); - } - - throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); - } - - internal DateTime? ReadDateTimeString(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, DateFormatString, Culture, out var dt)) - { - dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); - SetToken(JsonToken.Date, dt, false); - return dt; - } - - if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) - { - dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); - SetToken(JsonToken.Date, dt, false); - return dt; - } - - throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Reads the next JSON token from the source as a of . - /// - /// A of . This method will return null at the end of an array. - public virtual DateTimeOffset? ReadAsDateTimeOffset() - { - JsonToken t = GetContentToken(); - - switch (t) - { - case JsonToken.None: - case JsonToken.Null: - case JsonToken.EndArray: - return null; - case JsonToken.Date: - if (Value is DateTime time) - { - SetToken(JsonToken.Date, new DateTimeOffset(time), false); - } - - return (DateTimeOffset)Value!; - case JsonToken.String: - string? s = (string?)Value; - return ReadDateTimeOffsetString(s); - default: - throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); - } - } - - internal DateTimeOffset? ReadDateTimeOffsetString(string? s) - { - if (StringUtils.IsNullOrEmpty(s)) - { - SetToken(JsonToken.Null, null, false); - return null; - } - - if (DateTimeUtils.TryParseDateTimeOffset(s, DateFormatString, Culture, out DateTimeOffset dt)) - { - SetToken(JsonToken.Date, dt, false); - return dt; - } - - if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) - { - SetToken(JsonToken.Date, dt, false); - return dt; - } - - SetToken(JsonToken.String, s, false); - throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); - } -#endif - - internal void ReaderReadAndAssert() - { - if (!Read()) throw CreateUnexpectedEndException(); - } - - internal JsonReaderException CreateUnexpectedEndException() => JsonReaderException.Create(this, "Unexpected end when reading JSON."); - - internal void ReadIntoWrappedTypeObject() - { - ReaderReadAndAssert(); - if (Value != null && Value.ToString() == JsonTypeReflector.TypePropertyName) - { - ReaderReadAndAssert(); - if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) - { - ReaderReadAndAssert(); - if (Value.ToString() == JsonTypeReflector.ValuePropertyName) return; - } - } - - throw JsonReaderException.Create(this, - "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); - } - - /// - /// Skips the children of the current token. - /// - public void Skip() - { - if (TokenType == JsonToken.PropertyName) Read(); - - if (JsonTokenUtils.IsStartToken(TokenType)) - { - var depth = Depth; - - while (Read() && depth < Depth) { } - } - } - - /// - /// Sets the current token. - /// - /// The new token. - protected void SetToken(JsonToken newToken) => SetToken(newToken, null, true); - - /// - /// Sets the current token and value. - /// - /// The new token. - /// The value. - protected void SetToken(JsonToken newToken, object? value) => SetToken(newToken, value, true); - - /// - /// Sets the current token and value. - /// - /// The new token. - /// The value. - /// A flag indicating whether the position index inside an array should be updated. - protected void SetToken(JsonToken newToken, object? value, bool updateIndex) - { - _tokenType = newToken; - _value = value; - - switch (newToken) - { - case JsonToken.StartObject: - _currentState = State.ObjectStart; - Push(JsonContainerType.Object); - break; - case JsonToken.StartArray: - _currentState = State.ArrayStart; - Push(JsonContainerType.Array); - break; - case JsonToken.StartConstructor: - _currentState = State.ConstructorStart; - Push(JsonContainerType.Constructor); - break; - case JsonToken.EndObject: - ValidateEnd(JsonToken.EndObject); - break; - case JsonToken.EndArray: - ValidateEnd(JsonToken.EndArray); - break; - case JsonToken.EndConstructor: - ValidateEnd(JsonToken.EndConstructor); - break; - case JsonToken.PropertyName: - _currentState = State.Property; - - _currentPosition.PropertyName = (string)value!; - break; - case JsonToken.Undefined: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Boolean: - case JsonToken.Null: - case JsonToken.Date: - case JsonToken.String: - case JsonToken.Raw: - case JsonToken.Bytes: - SetPostValueState(updateIndex); - break; - } - } - - internal void SetPostValueState(bool updateIndex) - { - if (Peek() != JsonContainerType.None || SupportMultipleContent) - _currentState = State.PostValue; - else - SetFinished(); - - if (updateIndex) UpdateScopeWithFinishedValue(); - } - - private void UpdateScopeWithFinishedValue() - { - if (_currentPosition.HasIndex) _currentPosition.Position++; - } - - private void ValidateEnd(JsonToken endToken) - { - var currentObject = Pop(); - - if (GetTypeForCloseToken(endToken) != currentObject) - throw JsonReaderException.Create(this, - "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject)); - - if (Peek() != JsonContainerType.None || SupportMultipleContent) - _currentState = State.PostValue; - else - SetFinished(); - } - - /// - /// Sets the state based on current token type. - /// - protected void SetStateBasedOnCurrent() - { - var currentObject = Peek(); - - switch (currentObject) - { - case JsonContainerType.Object: - _currentState = State.Object; - break; - case JsonContainerType.Array: - _currentState = State.Array; - break; - case JsonContainerType.Constructor: - _currentState = State.Constructor; - break; - case JsonContainerType.None: - SetFinished(); - break; - default: - throw JsonReaderException.Create(this, - "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith( - CultureInfo.InvariantCulture, currentObject)); - } - } - - private void SetFinished() => _currentState = SupportMultipleContent ? State.Start : State.Finished; - - private JsonContainerType GetTypeForCloseToken(JsonToken token) - { - switch (token) - { - case JsonToken.EndObject: - return JsonContainerType.Object; - case JsonToken.EndArray: - return JsonContainerType.Array; - case JsonToken.EndConstructor: - return JsonContainerType.Constructor; - default: - throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)); - } - } - - void IDisposable.Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// true to release both managed and unmanaged resources; false to release only - /// unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (_currentState != State.Closed && disposing) Close(); - } - - /// - /// Changes the reader's state to . - /// If is set to true, the source is also closed. - /// - public virtual void Close() - { - _currentState = State.Closed; - _tokenType = JsonToken.None; - _value = null; - } - - internal void ReadAndAssert() - { - if (!Read()) throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); - } - - internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) - { - if (!ReadForType(contract, hasConverter)) throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); - } - - internal bool ReadForType(JsonContract? contract, bool hasConverter) - { - // don't read properties with converters as a specific value - // the value might be a string which will then get converted which will error if read as date for example - if (hasConverter) return Read(); - - var t = contract?.InternalReadType ?? ReadType.Read; - - switch (t) - { - case ReadType.Read: - return ReadAndMoveToContent(); - case ReadType.ReadAsInt32: - ReadAsInt32(); - break; - case ReadType.ReadAsInt64: - var result = ReadAndMoveToContent(); - if (TokenType == JsonToken.Undefined) - throw JsonReaderException.Create(this, - "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, - contract?.UnderlyingType ?? typeof(long))); - - return result; - case ReadType.ReadAsDecimal: - ReadAsDecimal(); - break; - case ReadType.ReadAsDouble: - ReadAsDouble(); - break; - case ReadType.ReadAsBytes: - ReadAsBytes(); - break; - case ReadType.ReadAsBoolean: - ReadAsBoolean(); - break; - case ReadType.ReadAsString: - ReadAsString(); - break; - case ReadType.ReadAsDateTime: - ReadAsDateTime(); - break; -#if HAVE_DATE_TIME_OFFSET - case ReadType.ReadAsDateTimeOffset: - ReadAsDateTimeOffset(); - break; -#endif - default: - throw new ArgumentOutOfRangeException(); - } - - return TokenType != JsonToken.None; - } - - internal bool ReadAndMoveToContent() => Read() && MoveToContent(); - - internal bool MoveToContent() - { - var t = TokenType; - while (t == JsonToken.None || t == JsonToken.Comment) - { - if (!Read()) return false; - - t = TokenType; - } - - return true; - } - - private JsonToken GetContentToken() - { - JsonToken t; - do - if (!Read()) - { - SetToken(JsonToken.None); - return JsonToken.None; - } - else - t = TokenType; - while (t == JsonToken.Comment); - - return t; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReaderException.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReaderException.cs deleted file mode 100644 index 01723c310..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonReaderException.cs +++ /dev/null @@ -1,145 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// The exception thrown when an error occurs while reading JSON text. - /// -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - [Serializable] -#endif - internal class JsonReaderException : JsonException - { - /// - /// Gets the line number indicating where the error occurred. - /// - /// The line number indicating where the error occurred. - public int LineNumber { get; } - - /// - /// Gets the line position indicating where the error occurred. - /// - /// The line position indicating where the error occurred. - public int LinePosition { get; } - - /// - /// Gets the path to the JSON where the error occurred. - /// - /// The path to the JSON where the error occurred. - public string? Path { get; } - - /// - /// Initializes a new instance of the class. - /// - public JsonReaderException() { } - - /// - /// Initializes a new instance of the class - /// with a specified error message. - /// - /// The error message that explains the reason for the exception. - public JsonReaderException(string message) - : base(message) { } - - /// - /// Initializes a new instance of the class - /// with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonReaderException(string message, Exception innerException) - : base(message, innerException) { } - -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// The parameter is null. - /// The class name is null or is zero (0). - public JsonReaderException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } -#endif - - /// - /// Initializes a new instance of the class - /// with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is - /// the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The path to the JSON where the error occurred. - /// The line number indicating where the error occurred. - /// The line position indicating where the error occurred. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) - : base(message, innerException) - { - Path = path; - LineNumber = lineNumber; - LinePosition = linePosition; - } - - internal static JsonReaderException Create(JsonReader reader, string message) => Create(reader, message, null); - - internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) => - Create(reader as IJsonLineInfo, reader.Path, message, ex); - - internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) - { - message = JsonPosition.FormatMessage(lineInfo, path, message); - - int lineNumber; - int linePosition; - if (lineInfo != null && lineInfo.HasLineInfo()) - { - lineNumber = lineInfo.LineNumber; - linePosition = lineInfo.LinePosition; - } - else - { - lineNumber = 0; - linePosition = 0; - } - - return new JsonReaderException(message, path, lineNumber, linePosition, ex); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonRequiredAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonRequiredAttribute.cs deleted file mode 100644 index 9028f3f32..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonRequiredAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Instructs the to always serialize the member, and to require that the member has a value. - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - internal sealed class JsonRequiredAttribute : Attribute { } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializationException.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializationException.cs deleted file mode 100644 index aaccab4aa..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializationException.cs +++ /dev/null @@ -1,145 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// The exception thrown when an error occurs during JSON serialization or deserialization. - /// -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - [Serializable] -#endif - internal class JsonSerializationException : JsonException - { - /// - /// Gets the line number indicating where the error occurred. - /// - /// The line number indicating where the error occurred. - public int LineNumber { get; } - - /// - /// Gets the line position indicating where the error occurred. - /// - /// The line position indicating where the error occurred. - public int LinePosition { get; } - - /// - /// Gets the path to the JSON where the error occurred. - /// - /// The path to the JSON where the error occurred. - public string? Path { get; } - - /// - /// Initializes a new instance of the class. - /// - public JsonSerializationException() { } - - /// - /// Initializes a new instance of the class - /// with a specified error message. - /// - /// The error message that explains the reason for the exception. - public JsonSerializationException(string message) - : base(message) { } - - /// - /// Initializes a new instance of the class - /// with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonSerializationException(string message, Exception innerException) - : base(message, innerException) { } - -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// The parameter is null. - /// The class name is null or is zero (0). - public JsonSerializationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } -#endif - - /// - /// Initializes a new instance of the class - /// with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is - /// the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The path to the JSON where the error occurred. - /// The line number indicating where the error occurred. - /// The line position indicating where the error occurred. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) - : base(message, innerException) - { - Path = path; - LineNumber = lineNumber; - LinePosition = linePosition; - } - - internal static JsonSerializationException Create(JsonReader reader, string message) => Create(reader, message, null); - - internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) => - Create(reader as IJsonLineInfo, reader.Path, message, ex); - - internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) - { - message = JsonPosition.FormatMessage(lineInfo, path, message); - - int lineNumber; - int linePosition; - if (lineInfo != null && lineInfo.HasLineInfo()) - { - lineNumber = lineInfo.LineNumber; - linePosition = lineInfo.LinePosition; - } - else - { - lineNumber = 0; - linePosition = 0; - } - - return new JsonSerializationException(message, path, lineNumber, linePosition, ex); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializer.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializer.cs deleted file mode 100644 index 34a350e65..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializer.cs +++ /dev/null @@ -1,991 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using ErrorEventArgs = Elastic.Apm.Libraries.Newtonsoft.Json.Serialization.ErrorEventArgs; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Serializes and deserializes objects into and from the JSON format. - /// The enables you to control how objects are encoded into JSON. - /// - internal class JsonSerializer - { - /// - /// Initializes a new instance of the class. - /// - public JsonSerializer() - { - _referenceLoopHandling = JsonSerializerSettings.DefaultReferenceLoopHandling; - _missingMemberHandling = JsonSerializerSettings.DefaultMissingMemberHandling; - _nullValueHandling = JsonSerializerSettings.DefaultNullValueHandling; - _defaultValueHandling = JsonSerializerSettings.DefaultDefaultValueHandling; - _objectCreationHandling = JsonSerializerSettings.DefaultObjectCreationHandling; - _preserveReferencesHandling = JsonSerializerSettings.DefaultPreserveReferencesHandling; - _constructorHandling = JsonSerializerSettings.DefaultConstructorHandling; - _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling; - _metadataPropertyHandling = JsonSerializerSettings.DefaultMetadataPropertyHandling; - _context = JsonSerializerSettings.DefaultContext; - _serializationBinder = DefaultSerializationBinder.Instance; - - _culture = JsonSerializerSettings.DefaultCulture; - _contractResolver = DefaultContractResolver.Instance; - } - - private bool? _checkAdditionalContent; - internal ConstructorHandling _constructorHandling; - internal StreamingContext _context; - internal IContractResolver _contractResolver; - internal JsonConverterCollection? _converters; - private CultureInfo _culture; - private DateFormatHandling? _dateFormatHandling; - private string? _dateFormatString; - private bool _dateFormatStringSet; - private DateParseHandling? _dateParseHandling; - private DateTimeZoneHandling? _dateTimeZoneHandling; - internal DefaultValueHandling _defaultValueHandling; - internal IEqualityComparer? _equalityComparer; - private FloatFormatHandling? _floatFormatHandling; - private FloatParseHandling? _floatParseHandling; - - private Formatting? _formatting; - private int? _maxDepth; - private bool _maxDepthSet; - internal MetadataPropertyHandling _metadataPropertyHandling; - internal MissingMemberHandling _missingMemberHandling; - internal NullValueHandling _nullValueHandling; - internal ObjectCreationHandling _objectCreationHandling; - internal PreserveReferencesHandling _preserveReferencesHandling; - internal ReferenceLoopHandling _referenceLoopHandling; - private IReferenceResolver? _referenceResolver; - internal ISerializationBinder _serializationBinder; - private StringEscapeHandling? _stringEscapeHandling; - internal ITraceWriter? _traceWriter; - internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; - internal TypeNameHandling _typeNameHandling; - - /// - /// Gets or sets the used by the serializer when resolving type names. - /// - [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] - public virtual SerializationBinder Binder - { - get - { - if (_serializationBinder is SerializationBinder legacySerializationBinder) return legacySerializationBinder; - - if (_serializationBinder is SerializationBinderAdapter adapter) return adapter.SerializationBinder; - - throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); - } - set - { - if (value == null) throw new ArgumentNullException(nameof(value), "Serialization binder cannot be null."); - - _serializationBinder = value as ISerializationBinder ?? new SerializationBinderAdapter(value); - } - } - - /// - /// Gets a value indicating whether there will be a check for additional JSON content after deserializing an object. - /// The default value is false. - /// - /// - /// true if there will be a check for additional JSON content after deserializing an object; otherwise, - /// false. - /// - public virtual bool CheckAdditionalContent - { - get => _checkAdditionalContent ?? JsonSerializerSettings.DefaultCheckAdditionalContent; - set => _checkAdditionalContent = value; - } - - /// - /// Gets or sets how constructors are used during deserialization. - /// The default value is . - /// - /// The constructor handling. - public virtual ConstructorHandling ConstructorHandling - { - get => _constructorHandling; - set - { - if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) - throw new ArgumentOutOfRangeException(nameof(value)); - - _constructorHandling = value; - } - } - - /// - /// Gets or sets the used by the serializer when invoking serialization callback methods. - /// - /// The context. - public virtual StreamingContext Context - { - get => _context; - set => _context = value; - } - - /// - /// Gets or sets the contract resolver used by the serializer when - /// serializing .NET objects to JSON and vice versa. - /// - public virtual IContractResolver ContractResolver - { - get => _contractResolver; - set => _contractResolver = value ?? DefaultContractResolver.Instance; - } - - /// - /// Gets a collection that will be used during serialization. - /// - /// Collection that will be used during serialization. - public virtual JsonConverterCollection Converters - { - get - { - if (_converters == null) _converters = new JsonConverterCollection(); - - return _converters; - } - } - - /// - /// Gets or sets the culture used when reading JSON. - /// The default value is . - /// - public virtual CultureInfo Culture - { - get => _culture ?? JsonSerializerSettings.DefaultCulture; - set => _culture = value; - } - - /// - /// Gets or sets how dates are written to JSON text. - /// The default value is . - /// - public virtual DateFormatHandling DateFormatHandling - { - get => _dateFormatHandling ?? JsonSerializerSettings.DefaultDateFormatHandling; - set => _dateFormatHandling = value; - } - - /// - /// Gets or sets how and values are formatted when writing JSON text, - /// and the expected date format when reading JSON text. - /// The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". - /// - public virtual string DateFormatString - { - get => _dateFormatString ?? JsonSerializerSettings.DefaultDateFormatString; - set - { - _dateFormatString = value; - _dateFormatStringSet = true; - } - } - - /// - /// Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are - /// parsed when reading JSON. - /// The default value is . - /// - public virtual DateParseHandling DateParseHandling - { - get => _dateParseHandling ?? JsonSerializerSettings.DefaultDateParseHandling; - set => _dateParseHandling = value; - } - - /// - /// Gets or sets how time zones are handled during serialization and deserialization. - /// The default value is . - /// - public virtual DateTimeZoneHandling DateTimeZoneHandling - { - get => _dateTimeZoneHandling ?? JsonSerializerSettings.DefaultDateTimeZoneHandling; - set => _dateTimeZoneHandling = value; - } - - /// - /// Gets or sets how default values are handled during serialization and deserialization. - /// The default value is . - /// - public virtual DefaultValueHandling DefaultValueHandling - { - get => _defaultValueHandling; - set - { - if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) - throw new ArgumentOutOfRangeException(nameof(value)); - - _defaultValueHandling = value; - } - } - - /// - /// Gets or sets the equality comparer used by the serializer when comparing references. - /// - /// The equality comparer. - public virtual IEqualityComparer? EqualityComparer - { - get => _equalityComparer; - set => _equalityComparer = value; - } - - /// - /// Gets or sets how special floating point numbers, e.g. , - /// and , - /// are written as JSON text. - /// The default value is . - /// - public virtual FloatFormatHandling FloatFormatHandling - { - get => _floatFormatHandling ?? JsonSerializerSettings.DefaultFloatFormatHandling; - set => _floatFormatHandling = value; - } - - /// - /// Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. - /// The default value is . - /// - public virtual FloatParseHandling FloatParseHandling - { - get => _floatParseHandling ?? JsonSerializerSettings.DefaultFloatParseHandling; - set => _floatParseHandling = value; - } - - /// - /// Indicates how JSON text output is formatted. - /// The default value is . - /// - public virtual Formatting Formatting - { - get => _formatting ?? JsonSerializerSettings.DefaultFormatting; - set => _formatting = value; - } - - /// - /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a - /// . - /// A null value means there is no maximum. - /// The default value is 128. - /// - public virtual int? MaxDepth - { - get => _maxDepth; - set - { - if (value <= 0) throw new ArgumentException("Value must be positive.", nameof(value)); - - _maxDepth = value; - _maxDepthSet = true; - } - } - - /// - /// Gets or sets how metadata properties are used during deserialization. - /// The default value is . - /// - /// The metadata properties handling. - public virtual MetadataPropertyHandling MetadataPropertyHandling - { - get => _metadataPropertyHandling; - set - { - if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) - throw new ArgumentOutOfRangeException(nameof(value)); - - _metadataPropertyHandling = value; - } - } - - /// - /// Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during - /// deserialization. - /// The default value is . - /// - public virtual MissingMemberHandling MissingMemberHandling - { - get => _missingMemberHandling; - set - { - if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) throw new ArgumentOutOfRangeException(nameof(value)); - - _missingMemberHandling = value; - } - } - - /// - /// Gets or sets how null values are handled during serialization and deserialization. - /// The default value is . - /// - public virtual NullValueHandling NullValueHandling - { - get => _nullValueHandling; - set - { - if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) throw new ArgumentOutOfRangeException(nameof(value)); - - _nullValueHandling = value; - } - } - - /// - /// Gets or sets how objects are created during deserialization. - /// The default value is . - /// - /// The object creation handling. - public virtual ObjectCreationHandling ObjectCreationHandling - { - get => _objectCreationHandling; - set - { - if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) - throw new ArgumentOutOfRangeException(nameof(value)); - - _objectCreationHandling = value; - } - } - - /// - /// Gets or sets how object references are preserved by the serializer. - /// The default value is . - /// - public virtual PreserveReferencesHandling PreserveReferencesHandling - { - get => _preserveReferencesHandling; - set - { - if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) - throw new ArgumentOutOfRangeException(nameof(value)); - - _preserveReferencesHandling = value; - } - } - - /// - /// Gets or sets how reference loops (e.g. a class referencing itself) is handled. - /// The default value is . - /// - public virtual ReferenceLoopHandling ReferenceLoopHandling - { - get => _referenceLoopHandling; - set - { - if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) - throw new ArgumentOutOfRangeException(nameof(value)); - - _referenceLoopHandling = value; - } - } - - /// - /// Gets or sets the used by the serializer when resolving references. - /// - public virtual IReferenceResolver? ReferenceResolver - { - get => GetReferenceResolver(); - set - { - if (value == null) throw new ArgumentNullException(nameof(value), "Reference resolver cannot be null."); - - _referenceResolver = value; - } - } - - /// - /// Gets or sets the used by the serializer when resolving type names. - /// - public virtual ISerializationBinder SerializationBinder - { - get => _serializationBinder; - set - { - if (value == null) throw new ArgumentNullException(nameof(value), "Serialization binder cannot be null."); - - _serializationBinder = value; - } - } - - /// - /// Gets or sets how strings are escaped when writing JSON text. - /// The default value is . - /// - public virtual StringEscapeHandling StringEscapeHandling - { - get => _stringEscapeHandling ?? JsonSerializerSettings.DefaultStringEscapeHandling; - set => _stringEscapeHandling = value; - } - - /// - /// Gets or sets the used by the serializer when writing trace messages. - /// - /// The trace writer. - public virtual ITraceWriter? TraceWriter - { - get => _traceWriter; - set => _traceWriter = value; - } - - /// - /// Gets or sets how a type name assembly is written and resolved by the serializer. - /// The default value is . - /// - /// The type name assembly format. - [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] - public virtual FormatterAssemblyStyle TypeNameAssemblyFormat - { - get => (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; - set - { - if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) - throw new ArgumentOutOfRangeException(nameof(value)); - - _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; - } - } - - /// - /// Gets or sets how a type name assembly is written and resolved by the serializer. - /// The default value is . - /// - /// The type name assembly format. - public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling - { - get => _typeNameAssemblyFormatHandling; - set - { - if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) - throw new ArgumentOutOfRangeException(nameof(value)); - - _typeNameAssemblyFormatHandling = value; - } - } - - /// - /// Gets or sets how type name writing and reading is handled by the serializer. - /// The default value is . - /// - /// - /// should be used with caution when your application deserializes JSON from - /// an external source. - /// Incoming types should be validated with a custom - /// when deserializing with a value other than . - /// - public virtual TypeNameHandling TypeNameHandling - { - get => _typeNameHandling; - set - { - if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) throw new ArgumentOutOfRangeException(nameof(value)); - - _typeNameHandling = value; - } - } - - /// - /// Occurs when the errors during serialization and deserialization. - /// - public virtual event EventHandler? Error; - - internal bool IsCheckAdditionalContentSet() => _checkAdditionalContent != null; - - /// - /// Creates a new instance. - /// The will not use default settings - /// from . - /// - /// - /// A new instance. - /// The will not use default settings - /// from . - /// - public static JsonSerializer Create() => new(); - - /// - /// Creates a new instance using the specified . - /// The will not use default settings - /// from . - /// - /// The settings to be applied to the . - /// - /// A new instance using the specified . - /// The will not use default settings - /// from . - /// - public static JsonSerializer Create(JsonSerializerSettings? settings) - { - var serializer = Create(); - - if (settings != null) ApplySerializerSettings(serializer, settings); - - return serializer; - } - - /// - /// Creates a new instance. - /// The will use default settings - /// from . - /// - /// - /// A new instance. - /// The will use default settings - /// from . - /// - public static JsonSerializer CreateDefault() - { - // copy static to local variable to avoid concurrency issues - var defaultSettings = JsonConvert.DefaultSettings?.Invoke(); - - return Create(defaultSettings); - } - - /// - /// Creates a new instance using the specified . - /// The will use default settings - /// from as well as the specified . - /// - /// The settings to be applied to the . - /// - /// A new instance using the specified . - /// The will use default settings - /// from as well as the specified . - /// - public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) - { - var serializer = CreateDefault(); - if (settings != null) ApplySerializerSettings(serializer, settings); - - return serializer; - } - - private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) - { - if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) - { - // insert settings converters at the beginning so they take precedence - // if user wants to remove one of the default converters they will have to do it manually - for (var i = 0; i < settings.Converters.Count; i++) serializer.Converters.Insert(i, settings.Converters[i]); - } - - // serializer specific - if (settings._typeNameHandling != null) serializer.TypeNameHandling = settings.TypeNameHandling; - if (settings._metadataPropertyHandling != null) serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; - if (settings._typeNameAssemblyFormatHandling != null) serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; - if (settings._preserveReferencesHandling != null) serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; - if (settings._referenceLoopHandling != null) serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; - if (settings._missingMemberHandling != null) serializer.MissingMemberHandling = settings.MissingMemberHandling; - if (settings._objectCreationHandling != null) serializer.ObjectCreationHandling = settings.ObjectCreationHandling; - if (settings._nullValueHandling != null) serializer.NullValueHandling = settings.NullValueHandling; - if (settings._defaultValueHandling != null) serializer.DefaultValueHandling = settings.DefaultValueHandling; - if (settings._constructorHandling != null) serializer.ConstructorHandling = settings.ConstructorHandling; - if (settings._context != null) serializer.Context = settings.Context; - if (settings._checkAdditionalContent != null) serializer._checkAdditionalContent = settings._checkAdditionalContent; - - if (settings.Error != null) serializer.Error += settings.Error; - - if (settings.ContractResolver != null) serializer.ContractResolver = settings.ContractResolver; - if (settings.ReferenceResolverProvider != null) serializer.ReferenceResolver = settings.ReferenceResolverProvider(); - if (settings.TraceWriter != null) serializer.TraceWriter = settings.TraceWriter; - if (settings.EqualityComparer != null) serializer.EqualityComparer = settings.EqualityComparer; - if (settings.SerializationBinder != null) serializer.SerializationBinder = settings.SerializationBinder; - - // reader/writer specific - // unset values won't override reader/writer set values - if (settings._formatting != null) serializer._formatting = settings._formatting; - if (settings._dateFormatHandling != null) serializer._dateFormatHandling = settings._dateFormatHandling; - if (settings._dateTimeZoneHandling != null) serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; - if (settings._dateParseHandling != null) serializer._dateParseHandling = settings._dateParseHandling; - if (settings._dateFormatStringSet) - { - serializer._dateFormatString = settings._dateFormatString; - serializer._dateFormatStringSet = settings._dateFormatStringSet; - } - if (settings._floatFormatHandling != null) serializer._floatFormatHandling = settings._floatFormatHandling; - if (settings._floatParseHandling != null) serializer._floatParseHandling = settings._floatParseHandling; - if (settings._stringEscapeHandling != null) serializer._stringEscapeHandling = settings._stringEscapeHandling; - if (settings._culture != null) serializer._culture = settings._culture; - if (settings._maxDepthSet) - { - serializer._maxDepth = settings._maxDepth; - serializer._maxDepthSet = settings._maxDepthSet; - } - } - - /// - /// Populates the JSON values onto the target object. - /// - /// The that contains the JSON structure to read values from. - /// The target object to populate values onto. - [DebuggerStepThrough] - public void Populate(TextReader reader, object target) => Populate(new JsonTextReader(reader), target); - - /// - /// Populates the JSON values onto the target object. - /// - /// The that contains the JSON structure to read values from. - /// The target object to populate values onto. - [DebuggerStepThrough] - public void Populate(JsonReader reader, object target) => PopulateInternal(reader, target); - - internal virtual void PopulateInternal(JsonReader reader, object target) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - ValidationUtils.ArgumentNotNull(target, nameof(target)); - - SetupReader( - reader, - out var previousCulture, - out var previousDateTimeZoneHandling, - out var previousDateParseHandling, - out var previousFloatParseHandling, - out var previousMaxDepth, - out var previousDateFormatString); - - var traceJsonReader = TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose - ? CreateTraceJsonReader(reader) - : null; - - var serializerReader = new JsonSerializerInternalReader(this); - serializerReader.Populate(traceJsonReader ?? reader, target); - - if (traceJsonReader != null) TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); - - ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, - previousMaxDepth, previousDateFormatString); - } - - /// - /// Deserializes the JSON structure contained by the specified . - /// - /// The that contains the JSON structure to deserialize. - /// The being deserialized. - [DebuggerStepThrough] - public object? Deserialize(JsonReader reader) => Deserialize(reader, null); - - /// - /// Deserializes the JSON structure contained by the specified - /// into an instance of the specified type. - /// - /// The containing the object. - /// The of object being deserialized. - /// The instance of being deserialized. - [DebuggerStepThrough] - public object? Deserialize(TextReader reader, Type objectType) => Deserialize(new JsonTextReader(reader), objectType); - - /// - /// Deserializes the JSON structure contained by the specified - /// into an instance of the specified type. - /// - /// The containing the object. - /// The type of the object to deserialize. - /// The instance of being deserialized. - [DebuggerStepThrough] - public T? Deserialize(JsonReader reader) => (T?)Deserialize(reader, typeof(T)); - - /// - /// Deserializes the JSON structure contained by the specified - /// into an instance of the specified type. - /// - /// The containing the object. - /// The of object being deserialized. - /// The instance of being deserialized. - [DebuggerStepThrough] - public object? Deserialize(JsonReader reader, Type? objectType) => DeserializeInternal(reader, objectType); - - internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - SetupReader( - reader, - out var previousCulture, - out var previousDateTimeZoneHandling, - out var previousDateParseHandling, - out var previousFloatParseHandling, - out var previousMaxDepth, - out var previousDateFormatString); - - var traceJsonReader = TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose - ? CreateTraceJsonReader(reader) - : null; - - var serializerReader = new JsonSerializerInternalReader(this); - var value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); - - if (traceJsonReader != null) TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); - - ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, - previousMaxDepth, previousDateFormatString); - - return value; - } - - private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, - out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, - out string? previousDateFormatString - ) - { - if (_culture != null && !_culture.Equals(reader.Culture)) - { - previousCulture = reader.Culture; - reader.Culture = _culture; - } - else - previousCulture = null; - - if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling) - { - previousDateTimeZoneHandling = reader.DateTimeZoneHandling; - reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); - } - else - previousDateTimeZoneHandling = null; - - if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling) - { - previousDateParseHandling = reader.DateParseHandling; - reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); - } - else - previousDateParseHandling = null; - - if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling) - { - previousFloatParseHandling = reader.FloatParseHandling; - reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); - } - else - previousFloatParseHandling = null; - - if (_maxDepthSet && reader.MaxDepth != _maxDepth) - { - previousMaxDepth = reader.MaxDepth; - reader.MaxDepth = _maxDepth; - } - else - previousMaxDepth = null; - - if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) - { - previousDateFormatString = reader.DateFormatString; - reader.DateFormatString = _dateFormatString; - } - else - previousDateFormatString = null; - - if (reader is JsonTextReader textReader) - if (textReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver resolver) - textReader.PropertyNameTable = resolver.GetNameTable(); - } - - private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, - DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, - string? previousDateFormatString - ) - { - // reset reader back to previous options - if (previousCulture != null) reader.Culture = previousCulture; - if (previousDateTimeZoneHandling != null) reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); - if (previousDateParseHandling != null) reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); - if (previousFloatParseHandling != null) reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); - if (_maxDepthSet) reader.MaxDepth = previousMaxDepth; - if (_dateFormatStringSet) reader.DateFormatString = previousDateFormatString; - - if (reader is JsonTextReader textReader && textReader.PropertyNameTable != null && - _contractResolver is DefaultContractResolver resolver && textReader.PropertyNameTable == resolver.GetNameTable()) - textReader.PropertyNameTable = null; - } - - /// - /// Serializes the specified and writes the JSON structure - /// using the specified . - /// - /// The used to write the JSON structure. - /// The to serialize. - public void Serialize(TextWriter textWriter, object? value) => Serialize(new JsonTextWriter(textWriter), value); - - /// - /// Serializes the specified and writes the JSON structure - /// using the specified . - /// - /// The used to write the JSON structure. - /// The to serialize. - /// - /// The type of the value being serialized. - /// This parameter is used when is - /// to write out the type name if the type of the value does not match. - /// Specifying the type is optional. - /// - public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) => SerializeInternal(jsonWriter, value, objectType); - - /// - /// Serializes the specified and writes the JSON structure - /// using the specified . - /// - /// The used to write the JSON structure. - /// The to serialize. - /// - /// The type of the value being serialized. - /// This parameter is used when is Auto to write out the type name if the type of the value - /// does not match. - /// Specifying the type is optional. - /// - public void Serialize(TextWriter textWriter, object? value, Type objectType) => Serialize(new JsonTextWriter(textWriter), value, objectType); - - /// - /// Serializes the specified and writes the JSON structure - /// using the specified . - /// - /// The used to write the JSON structure. - /// The to serialize. - public void Serialize(JsonWriter jsonWriter, object? value) => SerializeInternal(jsonWriter, value, null); - - private TraceJsonReader CreateTraceJsonReader(JsonReader reader) - { - var traceReader = new TraceJsonReader(reader); - if (reader.TokenType != JsonToken.None) traceReader.WriteCurrentToken(); - - return traceReader; - } - - internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) - { - ValidationUtils.ArgumentNotNull(jsonWriter, nameof(jsonWriter)); - - // set serialization options onto writer - Formatting? previousFormatting = null; - if (_formatting != null && jsonWriter.Formatting != _formatting) - { - previousFormatting = jsonWriter.Formatting; - jsonWriter.Formatting = _formatting.GetValueOrDefault(); - } - - DateFormatHandling? previousDateFormatHandling = null; - if (_dateFormatHandling != null && jsonWriter.DateFormatHandling != _dateFormatHandling) - { - previousDateFormatHandling = jsonWriter.DateFormatHandling; - jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); - } - - DateTimeZoneHandling? previousDateTimeZoneHandling = null; - if (_dateTimeZoneHandling != null && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) - { - previousDateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; - jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); - } - - FloatFormatHandling? previousFloatFormatHandling = null; - if (_floatFormatHandling != null && jsonWriter.FloatFormatHandling != _floatFormatHandling) - { - previousFloatFormatHandling = jsonWriter.FloatFormatHandling; - jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); - } - - StringEscapeHandling? previousStringEscapeHandling = null; - if (_stringEscapeHandling != null && jsonWriter.StringEscapeHandling != _stringEscapeHandling) - { - previousStringEscapeHandling = jsonWriter.StringEscapeHandling; - jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); - } - - CultureInfo? previousCulture = null; - if (_culture != null && !_culture.Equals(jsonWriter.Culture)) - { - previousCulture = jsonWriter.Culture; - jsonWriter.Culture = _culture; - } - - string? previousDateFormatString = null; - if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) - { - previousDateFormatString = jsonWriter.DateFormatString; - jsonWriter.DateFormatString = _dateFormatString; - } - - var traceJsonWriter = TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose - ? new TraceJsonWriter(jsonWriter) - : null; - - var serializerWriter = new JsonSerializerInternalWriter(this); - serializerWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType); - - if (traceJsonWriter != null) TraceWriter!.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); - - // reset writer back to previous options - if (previousFormatting != null) jsonWriter.Formatting = previousFormatting.GetValueOrDefault(); - if (previousDateFormatHandling != null) jsonWriter.DateFormatHandling = previousDateFormatHandling.GetValueOrDefault(); - if (previousDateTimeZoneHandling != null) jsonWriter.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); - if (previousFloatFormatHandling != null) jsonWriter.FloatFormatHandling = previousFloatFormatHandling.GetValueOrDefault(); - if (previousStringEscapeHandling != null) jsonWriter.StringEscapeHandling = previousStringEscapeHandling.GetValueOrDefault(); - if (_dateFormatStringSet) jsonWriter.DateFormatString = previousDateFormatString; - if (previousCulture != null) jsonWriter.Culture = previousCulture; - } - - internal IReferenceResolver GetReferenceResolver() - { - if (_referenceResolver == null) _referenceResolver = new DefaultReferenceResolver(); - - return _referenceResolver; - } - - internal JsonConverter? GetMatchingConverter(Type type) => GetMatchingConverter(_converters, type); - - internal static JsonConverter? GetMatchingConverter(IList? converters, Type objectType) - { -#if DEBUG - ValidationUtils.ArgumentNotNull(objectType, nameof(objectType)); -#endif - - if (converters != null) - { - for (var i = 0; i < converters.Count; i++) - { - var converter = converters[i]; - - if (converter.CanConvert(objectType)) return converter; - } - } - - return null; - } - - internal void OnError(ErrorEventArgs e) => Error?.Invoke(this, e); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializerSettings.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializerSettings.cs deleted file mode 100644 index 85eb6589d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonSerializerSettings.cs +++ /dev/null @@ -1,452 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies the settings on a object. - /// - internal class JsonSerializerSettings - { - internal const bool DefaultCheckAdditionalContent = false; - internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; - internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; - internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; - internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; - internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; - internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; - internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; - internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; - - internal const Formatting DefaultFormatting = Formatting.None; - internal const int DefaultMaxDepth = 64; - internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; - internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; - internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; - internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; - internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; - internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; - internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; - internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; - internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; - internal static readonly StreamingContext DefaultContext; - internal static readonly CultureInfo DefaultCulture; - - static JsonSerializerSettings() - { - DefaultContext = new StreamingContext(); - DefaultCulture = CultureInfo.InvariantCulture; - } - - /// - /// Initializes a new instance of the class. - /// - [DebuggerStepThrough] - public JsonSerializerSettings() => Converters = new List(); - - internal bool? _checkAdditionalContent; - internal ConstructorHandling? _constructorHandling; - internal StreamingContext? _context; - internal CultureInfo? _culture; - internal DateFormatHandling? _dateFormatHandling; - internal string? _dateFormatString; - internal bool _dateFormatStringSet; - internal DateParseHandling? _dateParseHandling; - internal DateTimeZoneHandling? _dateTimeZoneHandling; - internal DefaultValueHandling? _defaultValueHandling; - internal FloatFormatHandling? _floatFormatHandling; - internal FloatParseHandling? _floatParseHandling; - - internal Formatting? _formatting; - internal int? _maxDepth; - internal bool _maxDepthSet; - internal MetadataPropertyHandling? _metadataPropertyHandling; - internal MissingMemberHandling? _missingMemberHandling; - internal NullValueHandling? _nullValueHandling; - internal ObjectCreationHandling? _objectCreationHandling; - internal PreserveReferencesHandling? _preserveReferencesHandling; - internal ReferenceLoopHandling? _referenceLoopHandling; - internal StringEscapeHandling? _stringEscapeHandling; - internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; - internal TypeNameHandling? _typeNameHandling; - - /// - /// Gets or sets the used by the serializer when resolving type names. - /// - /// The binder. - [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] - public SerializationBinder? Binder - { - get - { - if (SerializationBinder == null) return null; - - if (SerializationBinder is SerializationBinderAdapter adapter) return adapter.SerializationBinder; - - throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); - } - set => SerializationBinder = value == null ? null : new SerializationBinderAdapter(value); - } - - /// - /// Gets a value indicating whether there will be a check for additional content after deserializing an object. - /// The default value is false. - /// - /// - /// true if there will be a check for additional content after deserializing an object; otherwise, false. - /// - public bool CheckAdditionalContent - { - get => _checkAdditionalContent ?? DefaultCheckAdditionalContent; - set => _checkAdditionalContent = value; - } - - /// - /// Gets or sets how constructors are used during deserialization. - /// The default value is . - /// - /// The constructor handling. - public ConstructorHandling ConstructorHandling - { - get => _constructorHandling ?? DefaultConstructorHandling; - set => _constructorHandling = value; - } - - /// - /// Gets or sets the used by the serializer when invoking serialization callback methods. - /// - /// The context. - public StreamingContext Context - { - get => _context ?? DefaultContext; - set => _context = value; - } - - /// - /// Gets or sets the contract resolver used by the serializer when - /// serializing .NET objects to JSON and vice versa. - /// - /// The contract resolver. - public IContractResolver? ContractResolver { get; set; } - - /// - /// Gets or sets a collection that will be used during serialization. - /// - /// The converters. - public IList Converters { get; set; } - - /// - /// Gets or sets the culture used when reading JSON. - /// The default value is . - /// - public CultureInfo Culture - { - get => _culture ?? DefaultCulture; - set => _culture = value; - } - - /// - /// Gets or sets how dates are written to JSON text. - /// The default value is . - /// - public DateFormatHandling DateFormatHandling - { - get => _dateFormatHandling ?? DefaultDateFormatHandling; - set => _dateFormatHandling = value; - } - - /// - /// Gets or sets how and values are formatted when writing JSON text, - /// and the expected date format when reading JSON text. - /// The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". - /// - public string DateFormatString - { - get => _dateFormatString ?? DefaultDateFormatString; - set - { - _dateFormatString = value; - _dateFormatStringSet = true; - } - } - - /// - /// Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are - /// parsed when reading JSON. - /// The default value is . - /// - public DateParseHandling DateParseHandling - { - get => _dateParseHandling ?? DefaultDateParseHandling; - set => _dateParseHandling = value; - } - - /// - /// Gets or sets how time zones are handled during serialization and deserialization. - /// The default value is . - /// - public DateTimeZoneHandling DateTimeZoneHandling - { - get => _dateTimeZoneHandling ?? DefaultDateTimeZoneHandling; - set => _dateTimeZoneHandling = value; - } - - /// - /// Gets or sets how default values are handled during serialization and deserialization. - /// The default value is . - /// - /// The default value handling. - public DefaultValueHandling DefaultValueHandling - { - get => _defaultValueHandling ?? DefaultDefaultValueHandling; - set => _defaultValueHandling = value; - } - - /// - /// Gets or sets the equality comparer used by the serializer when comparing references. - /// - /// The equality comparer. - public IEqualityComparer? EqualityComparer { get; set; } - - /// - /// Gets or sets the error handler called during serialization and deserialization. - /// - /// The error handler called during serialization and deserialization. - public EventHandler? Error { get; set; } - - /// - /// Gets or sets how special floating point numbers, e.g. , - /// and , - /// are written as JSON. - /// The default value is . - /// - public FloatFormatHandling FloatFormatHandling - { - get => _floatFormatHandling ?? DefaultFloatFormatHandling; - set => _floatFormatHandling = value; - } - - /// - /// Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. - /// The default value is . - /// - public FloatParseHandling FloatParseHandling - { - get => _floatParseHandling ?? DefaultFloatParseHandling; - set => _floatParseHandling = value; - } - - /// - /// Indicates how JSON text output is formatted. - /// The default value is . - /// - public Formatting Formatting - { - get => _formatting ?? DefaultFormatting; - set => _formatting = value; - } - - /// - /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a - /// . - /// A null value means there is no maximum. - /// The default value is 128. - /// - public int? MaxDepth - { - get => _maxDepthSet ? _maxDepth : DefaultMaxDepth; - set - { - if (value <= 0) throw new ArgumentException("Value must be positive.", nameof(value)); - - _maxDepth = value; - _maxDepthSet = true; - } - } - - /// - /// Gets or sets how metadata properties are used during deserialization. - /// The default value is . - /// - /// The metadata properties handling. - public MetadataPropertyHandling MetadataPropertyHandling - { - get => _metadataPropertyHandling ?? DefaultMetadataPropertyHandling; - set => _metadataPropertyHandling = value; - } - - /// - /// Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during - /// deserialization. - /// The default value is . - /// - /// Missing member handling. - public MissingMemberHandling MissingMemberHandling - { - get => _missingMemberHandling ?? DefaultMissingMemberHandling; - set => _missingMemberHandling = value; - } - - /// - /// Gets or sets how null values are handled during serialization and deserialization. - /// The default value is . - /// - /// Null value handling. - public NullValueHandling NullValueHandling - { - get => _nullValueHandling ?? DefaultNullValueHandling; - set => _nullValueHandling = value; - } - - /// - /// Gets or sets how objects are created during deserialization. - /// The default value is . - /// - /// The object creation handling. - public ObjectCreationHandling ObjectCreationHandling - { - get => _objectCreationHandling ?? DefaultObjectCreationHandling; - set => _objectCreationHandling = value; - } - - /// - /// Gets or sets how object references are preserved by the serializer. - /// The default value is . - /// - /// The preserve references handling. - public PreserveReferencesHandling PreserveReferencesHandling - { - get => _preserveReferencesHandling ?? DefaultPreserveReferencesHandling; - set => _preserveReferencesHandling = value; - } - - /// - /// Gets or sets how reference loops (e.g. a class referencing itself) are handled. - /// The default value is . - /// - /// Reference loop handling. - public ReferenceLoopHandling ReferenceLoopHandling - { - get => _referenceLoopHandling ?? DefaultReferenceLoopHandling; - set => _referenceLoopHandling = value; - } - - /// - /// Gets or sets the used by the serializer when resolving references. - /// - /// The reference resolver. - [Obsolete( - "ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] - public IReferenceResolver? ReferenceResolver - { - get => ReferenceResolverProvider?.Invoke(); - set => - ReferenceResolverProvider = value != null - ? () => value - : (Func?)null; - } - - /// - /// Gets or sets a function that creates the used by the serializer when resolving - /// references. - /// - /// A function that creates the used by the serializer when resolving references. - public Func? ReferenceResolverProvider { get; set; } - - /// - /// Gets or sets the used by the serializer when resolving type names. - /// - /// The binder. - public ISerializationBinder? SerializationBinder { get; set; } - - /// - /// Gets or sets how strings are escaped when writing JSON text. - /// The default value is . - /// - public StringEscapeHandling StringEscapeHandling - { - get => _stringEscapeHandling ?? DefaultStringEscapeHandling; - set => _stringEscapeHandling = value; - } - - /// - /// Gets or sets the used by the serializer when writing trace messages. - /// - /// The trace writer. - public ITraceWriter? TraceWriter { get; set; } - - /// - /// Gets or sets how a type name assembly is written and resolved by the serializer. - /// The default value is . - /// - /// The type name assembly format. - [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] - public FormatterAssemblyStyle TypeNameAssemblyFormat - { - get => (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling; - set => TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; - } - - /// - /// Gets or sets how a type name assembly is written and resolved by the serializer. - /// The default value is . - /// - /// The type name assembly format. - public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling - { - get => _typeNameAssemblyFormatHandling ?? DefaultTypeNameAssemblyFormatHandling; - set => _typeNameAssemblyFormatHandling = value; - } - - /// - /// Gets or sets how type name writing and reading is handled by the serializer. - /// The default value is . - /// - /// - /// should be used with caution when your application deserializes - /// JSON from an external source. - /// Incoming types should be validated with a custom - /// when deserializing with a value other than . - /// - /// The type name handling. - public TypeNameHandling TypeNameHandling - { - get => _typeNameHandling ?? DefaultTypeNameHandling; - set => _typeNameHandling = value; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.Async.cs deleted file mode 100644 index 822e7dd9d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.Async.cs +++ /dev/null @@ -1,1807 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -using System.Threading; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal partial class JsonTextReader - { - // It's not safe to perform the async methods here in a derived class as if the synchronous equivalent - // has been overriden then the asychronous method will no longer be doing the same operation -#if HAVE_ASYNC // Double-check this isn't included inappropriately. - private readonly bool _safeAsync; -#endif - - /// - /// Asynchronously reads the next JSON token from the source. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns true if the next token was read successfully; false if there are no more tokens to read. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsync(cancellationToken) : base.ReadAsync(cancellationToken); - } - - internal Task DoReadAsync(CancellationToken cancellationToken) - { - EnsureBuffer(); - - while (true) - { - switch (_currentState) - { - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - return ParseValueAsync(cancellationToken); - case State.Object: - case State.ObjectStart: - return ParseObjectAsync(cancellationToken); - case State.PostValue: - Task task = ParsePostValueAsync(false, cancellationToken); - if (task.IsCompletedSucessfully()) - { - if (task.Result) - { - return AsyncUtils.True; - } - } - else - { - return DoReadAsync(task, cancellationToken); - } - break; - case State.Finished: - return ReadFromFinishedAsync(cancellationToken); - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - } - - private async Task DoReadAsync(Task task, CancellationToken cancellationToken) - { - bool result = await task.ConfigureAwait(false); - if (result) - { - return true; - } - return await DoReadAsync(cancellationToken).ConfigureAwait(false); - } - - private async Task ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(false, cancellationToken).ConfigureAwait(false) == 0) - { - _currentState = State.Finished; - return false; - } - } - else - { - CharPos++; - } - - break; - case '}': - CharPos++; - SetToken(JsonToken.EndObject); - return true; - case ']': - CharPos++; - SetToken(JsonToken.EndArray); - return true; - case ')': - CharPos++; - SetToken(JsonToken.EndConstructor); - return true; - case '/': - await ParseCommentAsync(!ignoreComments, cancellationToken).ConfigureAwait(false); - if (!ignoreComments) - { - return true; - } - break; - case ',': - CharPos++; - - // finished parsing - SetStateBasedOnCurrent(); - return false; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - } - else - { - // handle multiple content without comma delimiter - if (SupportMultipleContent && Depth == 0) - { - SetStateBasedOnCurrent(); - return false; - } - - throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); - } - - break; - } - } - } - - private async Task ReadFromFinishedAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) - { - await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); - if (_isEndOfFile) - { - SetToken(JsonToken.None); - return false; - } - - if (CharBuffer[CharPos] == '/') - { - await ParseCommentAsync(true, cancellationToken).ConfigureAwait(false); - return true; - } - - throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - - SetToken(JsonToken.None); - return false; - } - - private Task ReadDataAsync(bool append, CancellationToken cancellationToken) - { - return ReadDataAsync(append, 0, cancellationToken); - } - - private async Task ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (_isEndOfFile) - { - return 0; - } - - PrepareBufferForReadData(append, charsRequired); - - int charsRead = await _reader.ReadAsync(CharBuffer, _charsUsed, CharBuffer.Length - _charsUsed - 1, cancellationToken).ConfigureAwait(false); - - _charsUsed += charsRead; - - if (charsRead == 0) - { - _isEndOfFile = true; - } - - CharBuffer[_charsUsed] = '\0'; - return charsRead; - } - - private async Task ParseValueAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(false, cancellationToken).ConfigureAwait(false) == 0) - { - return false; - } - } - else - { - CharPos++; - } - - break; - case '"': - case '\'': - await ParseStringAsync(currentChar, ReadType.Read, cancellationToken).ConfigureAwait(false); - return true; - case 't': - await ParseTrueAsync(cancellationToken).ConfigureAwait(false); - return true; - case 'f': - await ParseFalseAsync(cancellationToken).ConfigureAwait(false); - return true; - case 'n': - if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false)) - { - switch (CharBuffer[CharPos + 1]) - { - case 'u': - await ParseNullAsync(cancellationToken).ConfigureAwait(false); - break; - case 'e': - await ParseConstructorAsync(cancellationToken).ConfigureAwait(false); - break; - default: - throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - } - } - else - { - CharPos++; - throw CreateUnexpectedEndException(); - } - - return true; - case 'N': - await ParseNumberNaNAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - return true; - case 'I': - await ParseNumberPositiveInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - return true; - case '-': - if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false) && CharBuffer[CharPos + 1] == 'I') - { - await ParseNumberNegativeInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - } - else - { - await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - } - return true; - case '/': - await ParseCommentAsync(true, cancellationToken).ConfigureAwait(false); - return true; - case 'u': - await ParseUndefinedAsync(cancellationToken).ConfigureAwait(false); - return true; - case '{': - CharPos++; - SetToken(JsonToken.StartObject); - return true; - case '[': - CharPos++; - SetToken(JsonToken.StartArray); - return true; - case ']': - CharPos++; - SetToken(JsonToken.EndArray); - return true; - case ',': - - // don't increment position, the next call to read will handle comma - // this is done to handle multiple empty comma values - SetToken(JsonToken.Undefined); - return true; - case ')': - CharPos++; - SetToken(JsonToken.EndConstructor); - return true; - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - break; - } - - if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.') - { - await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - return true; - } - - throw CreateUnexpectedCharacterException(currentChar); - } - } - } - - private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - int charPos = CharPos; - int initialPosition = CharPos; - int lastWritePosition = CharPos; - _stringBuffer.Position = 0; - - while (true) - { - switch (CharBuffer[charPos++]) - { - case '\0': - if (_charsUsed == charPos - 1) - { - charPos--; - - if (await ReadDataAsync(true, cancellationToken).ConfigureAwait(false) == 0) - { - CharPos = charPos; - throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); - } - } - - break; - case '\\': - CharPos = charPos; - if (!await EnsureCharsAsync(0, true, cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); - } - - // start of escape sequence - int escapeStartPos = charPos - 1; - - char currentChar = CharBuffer[charPos]; - charPos++; - - char writeChar; - - switch (currentChar) - { - case 'b': - writeChar = '\b'; - break; - case 't': - writeChar = '\t'; - break; - case 'n': - writeChar = '\n'; - break; - case 'f': - writeChar = '\f'; - break; - case 'r': - writeChar = '\r'; - break; - case '\\': - writeChar = '\\'; - break; - case '"': - case '\'': - case '/': - writeChar = currentChar; - break; - case 'u': - CharPos = charPos; - writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(false); - - if (StringUtils.IsLowSurrogate(writeChar)) - { - // low surrogate with no preceding high surrogate; this char is replaced - writeChar = UnicodeReplacementChar; - } - else if (StringUtils.IsHighSurrogate(writeChar)) - { - bool anotherHighSurrogate; - - // loop for handling situations where there are multiple consecutive high surrogates - do - { - anotherHighSurrogate = false; - - // potential start of a surrogate pair - if (await EnsureCharsAsync(2, true, cancellationToken).ConfigureAwait(false) && CharBuffer[CharPos] == '\\' && CharBuffer[CharPos + 1] == 'u') - { - char highSurrogate = writeChar; - - CharPos += 2; - writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(false); - - if (StringUtils.IsLowSurrogate(writeChar)) - { - // a valid surrogate pair! - } - else if (StringUtils.IsHighSurrogate(writeChar)) - { - // another high surrogate; replace current and start check over - highSurrogate = UnicodeReplacementChar; - anotherHighSurrogate = true; - } - else - { - // high surrogate not followed by low surrogate; original char is replaced - highSurrogate = UnicodeReplacementChar; - } - - EnsureBufferNotEmpty(); - - WriteCharToBuffer(highSurrogate, lastWritePosition, escapeStartPos); - lastWritePosition = CharPos; - } - else - { - // there are not enough remaining chars for the low surrogate or is not follow by unicode sequence - // replace high surrogate and continue on as usual - writeChar = UnicodeReplacementChar; - } - } while (anotherHighSurrogate); - } - - charPos = CharPos; - break; - default: - CharPos = charPos; - throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar)); - } - - EnsureBufferNotEmpty(); - WriteCharToBuffer(writeChar, lastWritePosition, escapeStartPos); - - lastWritePosition = charPos; - break; - case StringUtils.CarriageReturn: - CharPos = charPos - 1; - await ProcessCarriageReturnAsync(true, cancellationToken).ConfigureAwait(false); - charPos = CharPos; - break; - case StringUtils.LineFeed: - CharPos = charPos - 1; - ProcessLineFeed(); - charPos = CharPos; - break; - case '"': - case '\'': - if (CharBuffer[charPos - 1] == quote) - { - FinishReadStringIntoBuffer(charPos - 1, initialPosition, lastWritePosition); - return; - } - - break; - } - } - } - - private Task ProcessCarriageReturnAsync(bool append, CancellationToken cancellationToken) - { - CharPos++; - - Task task = EnsureCharsAsync(1, append, cancellationToken); - if (task.IsCompletedSucessfully()) - { - SetNewLine(task.Result); - return AsyncUtils.CompletedTask; - } - - return ProcessCarriageReturnAsync(task); - } - - private async Task ProcessCarriageReturnAsync(Task task) - { - SetNewLine(await task.ConfigureAwait(false)); - } - - private async Task ParseUnicodeAsync(CancellationToken cancellationToken) - { - return ConvertUnicode(await EnsureCharsAsync(4, true, cancellationToken).ConfigureAwait(false)); - } - - private Task EnsureCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) - { - if (CharPos + relativePosition < _charsUsed) - { - return AsyncUtils.True; - } - - if (_isEndOfFile) - { - return AsyncUtils.False; - } - - return ReadCharsAsync(relativePosition, append, cancellationToken); - } - - private async Task ReadCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) - { - int charsRequired = CharPos + relativePosition - _charsUsed + 1; - - // it is possible that the TextReader doesn't return all data at once - // repeat read until the required text is returned or the reader is out of content - do - { - int charsRead = await ReadDataAsync(append, charsRequired, cancellationToken).ConfigureAwait(false); - - // no more content - if (charsRead == 0) - { - return false; - } - - charsRequired -= charsRead; - } while (charsRequired > 0); - - return true; - } - - private async Task ParseObjectAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(false, cancellationToken).ConfigureAwait(false) == 0) - { - return false; - } - } - else - { - CharPos++; - } - - break; - case '}': - SetToken(JsonToken.EndObject); - CharPos++; - return true; - case '/': - await ParseCommentAsync(true, cancellationToken).ConfigureAwait(false); - return true; - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - } - else - { - return await ParsePropertyAsync(cancellationToken).ConfigureAwait(false); - } - - break; - } - } - } - - private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // should have already parsed / character before reaching this method - CharPos++; - - if (!await EnsureCharsAsync(1, false, cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); - } - - bool singlelineComment; - - if (CharBuffer[CharPos] == '*') - { - singlelineComment = false; - } - else if (CharBuffer[CharPos] == '/') - { - singlelineComment = true; - } - else - { - throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - - CharPos++; - - int initialPosition = CharPos; - - while (true) - { - switch (CharBuffer[CharPos]) - { - case '\0': - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(true, cancellationToken).ConfigureAwait(false) == 0) - { - if (!singlelineComment) - { - throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); - } - - EndComment(setToken, initialPosition, CharPos); - return; - } - } - else - { - CharPos++; - } - - break; - case '*': - CharPos++; - - if (!singlelineComment) - { - if (await EnsureCharsAsync(0, true, cancellationToken).ConfigureAwait(false)) - { - if (CharBuffer[CharPos] == '/') - { - EndComment(setToken, initialPosition, CharPos - 1); - - CharPos++; - return; - } - } - } - - break; - case StringUtils.CarriageReturn: - if (singlelineComment) - { - EndComment(setToken, initialPosition, CharPos); - return; - } - - await ProcessCarriageReturnAsync(true, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - if (singlelineComment) - { - EndComment(setToken, initialPosition, CharPos); - return; - } - - ProcessLineFeed(); - break; - default: - CharPos++; - break; - } - } - } - - private async Task EatWhitespaceAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(false, cancellationToken).ConfigureAwait(false) == 0) - { - return; - } - } - else - { - CharPos++; - } - break; - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - default: - if (currentChar == ' ' || char.IsWhiteSpace(currentChar)) - { - CharPos++; - } - else - { - return; - } - break; - } - } - } - - private async Task ParseStringAsync(char quote, ReadType readType, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - CharPos++; - - ShiftBufferIfNeeded(); - await ReadStringIntoBufferAsync(quote, cancellationToken).ConfigureAwait(false); - ParseReadString(quote, readType); - } - - private async Task MatchValueAsync(string value, CancellationToken cancellationToken) - { - return MatchValue(await EnsureCharsAsync(value.Length - 1, true, cancellationToken).ConfigureAwait(false), value); - } - - private async Task MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // will match value and then move to the next character, checking that it is a separator character - if (!await MatchValueAsync(value, cancellationToken).ConfigureAwait(false)) - { - return false; - } - - if (!await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) - { - return true; - } - - return IsSeparator(CharBuffer[CharPos]) || CharBuffer[CharPos] == '\0'; - } - - private async Task MatchAndSetAsync(string value, JsonToken newToken, object? tokenValue, CancellationToken cancellationToken) - { - if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(false)) - { - SetToken(newToken, tokenValue); - } - else - { - throw JsonReaderException.Create(this, "Error parsing " + newToken.ToString().ToLowerInvariant() + " value."); - } - } - - private Task ParseTrueAsync(CancellationToken cancellationToken) - { - return MatchAndSetAsync(JsonConvert.True, JsonToken.Boolean, true, cancellationToken); - } - - private Task ParseFalseAsync(CancellationToken cancellationToken) - { - return MatchAndSetAsync(JsonConvert.False, JsonToken.Boolean, false, cancellationToken); - } - - private Task ParseNullAsync(CancellationToken cancellationToken) - { - return MatchAndSetAsync(JsonConvert.Null, JsonToken.Null, null, cancellationToken); - } - - private async Task ParseConstructorAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(false)) - { - await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); - - int initialPosition = CharPos; - int endPosition; - - while (true) - { - char currentChar = CharBuffer[CharPos]; - if (currentChar == '\0') - { - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(true, cancellationToken).ConfigureAwait(false) == 0) - { - throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); - } - } - else - { - endPosition = CharPos; - CharPos++; - break; - } - } - else if (char.IsLetterOrDigit(currentChar)) - { - CharPos++; - } - else if (currentChar == StringUtils.CarriageReturn) - { - endPosition = CharPos; - await ProcessCarriageReturnAsync(true, cancellationToken).ConfigureAwait(false); - break; - } - else if (currentChar == StringUtils.LineFeed) - { - endPosition = CharPos; - ProcessLineFeed(); - break; - } - else if (char.IsWhiteSpace(currentChar)) - { - endPosition = CharPos; - CharPos++; - break; - } - else if (currentChar == '(') - { - endPosition = CharPos; - break; - } - else - { - throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); - } - } - - _stringReference = new StringReference(CharBuffer, initialPosition, endPosition - initialPosition); - string constructorName = _stringReference.ToString(); - - await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); - - if (CharBuffer[CharPos] != '(') - { - throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - - CharPos++; - - ClearRecentString(); - - SetToken(JsonToken.StartConstructor, constructorName); - } - else - { - throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); - } - } - - private async Task ParseNumberNaNAsync(ReadType readType, CancellationToken cancellationToken) - { - return ParseNumberNaN(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NaN, cancellationToken).ConfigureAwait(false)); - } - - private async Task ParseNumberPositiveInfinityAsync(ReadType readType, CancellationToken cancellationToken) - { - return ParseNumberPositiveInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.PositiveInfinity, cancellationToken).ConfigureAwait(false)); - } - - private async Task ParseNumberNegativeInfinityAsync(ReadType readType, CancellationToken cancellationToken) - { - return ParseNumberNegativeInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NegativeInfinity, cancellationToken).ConfigureAwait(false)); - } - - private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - ShiftBufferIfNeeded(); - - char firstChar = CharBuffer[CharPos]; - int initialPosition = CharPos; - - await ReadNumberIntoBufferAsync(cancellationToken).ConfigureAwait(false); - - ParseReadNumber(readType, firstChar, initialPosition); - } - - private Task ParseUndefinedAsync(CancellationToken cancellationToken) - { - return MatchAndSetAsync(JsonConvert.Undefined, JsonToken.Undefined, null, cancellationToken); - } - - private async Task ParsePropertyAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - char firstChar = CharBuffer[CharPos]; - char quoteChar; - - if (firstChar == '"' || firstChar == '\'') - { - CharPos++; - quoteChar = firstChar; - ShiftBufferIfNeeded(); - await ReadStringIntoBufferAsync(quoteChar, cancellationToken).ConfigureAwait(false); - } - else if (ValidIdentifierChar(firstChar)) - { - quoteChar = '\0'; - ShiftBufferIfNeeded(); - await ParseUnquotedPropertyAsync(cancellationToken).ConfigureAwait(false); - } - else - { - throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - - string propertyName; - - if (PropertyNameTable != null) - { - propertyName = PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) - // no match in name table - ?? _stringReference.ToString(); - } - else - { - propertyName = _stringReference.ToString(); - } - - await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); - - if (CharBuffer[CharPos] != ':') - { - throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - - CharPos++; - - SetToken(JsonToken.PropertyName, propertyName); - _quoteChar = quoteChar; - ClearRecentString(); - - return true; - } - - private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - int charPos = CharPos; - - while (true) - { - char currentChar = CharBuffer[charPos]; - if (currentChar == '\0') - { - CharPos = charPos; - - if (_charsUsed == charPos) - { - if (await ReadDataAsync(true, cancellationToken).ConfigureAwait(false) == 0) - { - return; - } - } - else - { - return; - } - } - else if (ReadNumberCharIntoBuffer(currentChar, charPos)) - { - return; - } - else - { - charPos++; - } - } - } - - private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - int initialPosition = CharPos; - - // parse unquoted property name until whitespace or colon - while (true) - { - char currentChar = CharBuffer[CharPos]; - if (currentChar == '\0') - { - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(true, cancellationToken).ConfigureAwait(false) == 0) - { - throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); - } - - continue; - } - - _stringReference = new StringReference(CharBuffer, initialPosition, CharPos - initialPosition); - return; - } - - if (ReadUnquotedPropertyReportIfDone(currentChar, initialPosition)) - { - return; - } - } - } - - private async Task ReadNullCharAsync(CancellationToken cancellationToken) - { - if (_charsUsed == CharPos) - { - if (await ReadDataAsync(false, cancellationToken).ConfigureAwait(false) == 0) - { - _isEndOfFile = true; - return true; - } - } - else - { - CharPos++; - } - - return false; - } - - private async Task HandleNullAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false)) - { - if (CharBuffer[CharPos + 1] == 'u') - { - await ParseNullAsync(cancellationToken).ConfigureAwait(false); - return; - } - - CharPos += 2; - throw CreateUnexpectedCharacterException(CharBuffer[CharPos - 1]); - } - - CharPos = _charsUsed; - throw CreateUnexpectedEndException(); - } - - private async Task ReadFinishedAsync(CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) - { - await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); - if (_isEndOfFile) - { - SetToken(JsonToken.None); - return; - } - - if (CharBuffer[CharPos] == '/') - { - await ParseCommentAsync(false, cancellationToken).ConfigureAwait(false); - } - else - { - throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - } - } - - SetToken(JsonToken.None); - } - - private async Task ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (await ParsePostValueAsync(true, cancellationToken).ConfigureAwait(false)) - { - return null; - } - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(false)) - { - SetToken(JsonToken.None, null, false); - return null; - } - - break; - case '"': - case '\'': - await ParseStringAsync(currentChar, readType, cancellationToken).ConfigureAwait(false); - return FinishReadQuotedStringValue(readType); - case '-': - if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false) && CharBuffer[CharPos + 1] == 'I') - { - return ParseNumberNegativeInfinity(readType); - } - else - { - await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(false); - return Value; - } - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (readType != ReadType.ReadAsString) - { - CharPos++; - throw CreateUnexpectedCharacterException(currentChar); - } - - await ParseNumberAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false); - return Value; - case 't': - case 'f': - if (readType != ReadType.ReadAsString) - { - CharPos++; - throw CreateUnexpectedCharacterException(currentChar); - } - - string expected = currentChar == 't' ? JsonConvert.True : JsonConvert.False; - if (!await MatchValueWithTrailingSeparatorAsync(expected, cancellationToken).ConfigureAwait(false)) - { - throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - } - - SetToken(JsonToken.String, expected); - return expected; - case 'I': - return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(false); - case 'N': - return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(false); - case 'n': - await HandleNullAsync(cancellationToken).ConfigureAwait(false); - return null; - case '/': - await ParseCommentAsync(false, cancellationToken).ConfigureAwait(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) - { - throw CreateUnexpectedCharacterException(currentChar); - } - - // eat - break; - } - } - case State.Finished: - await ReadFinishedAsync(cancellationToken).ConfigureAwait(false); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private async Task ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (await ParsePostValueAsync(true, cancellationToken).ConfigureAwait(false)) - { - return null; - } - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(false)) - { - SetToken(JsonToken.None, null, false); - return null; - } - - break; - case '"': - case '\'': - await ParseStringAsync(currentChar, readType, cancellationToken).ConfigureAwait(false); - return FinishReadQuotedNumber(readType); - case 'n': - await HandleNullAsync(cancellationToken).ConfigureAwait(false); - return null; - case 'N': - return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(false); - case 'I': - return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(false); - case '-': - if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false) && CharBuffer[CharPos + 1] == 'I') - { - return await ParseNumberNegativeInfinityAsync(readType, cancellationToken).ConfigureAwait(false); - } - else - { - await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(false); - return Value; - } - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(false); - return Value; - case '/': - await ParseCommentAsync(false, cancellationToken).ConfigureAwait(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) - { - throw CreateUnexpectedCharacterException(currentChar); - } - - // eat - break; - } - } - case State.Finished: - await ReadFinishedAsync(cancellationToken).ConfigureAwait(false); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsBooleanAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsBooleanAsync(cancellationToken) : base.ReadAsBooleanAsync(cancellationToken); - } - - internal async Task DoReadAsBooleanAsync(CancellationToken cancellationToken) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (await ParsePostValueAsync(true, cancellationToken).ConfigureAwait(false)) - { - return null; - } - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(false)) - { - SetToken(JsonToken.None, null, false); - return null; - } - - break; - case '"': - case '\'': - await ParseStringAsync(currentChar, ReadType.Read, cancellationToken).ConfigureAwait(false); - return ReadBooleanString(_stringReference.ToString()); - case 'n': - await HandleNullAsync(cancellationToken).ConfigureAwait(false); - return null; - case '-': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(false); - bool b; -#if HAVE_BIG_INTEGER - if (Value is BigInteger i) - { - b = i != 0; - } - else -#endif - { - b = Convert.ToBoolean(Value, CultureInfo.InvariantCulture); - } - SetToken(JsonToken.Boolean, b, false); - return b; - case 't': - case 'f': - bool isTrue = currentChar == 't'; - if (!await MatchValueWithTrailingSeparatorAsync(isTrue ? JsonConvert.True : JsonConvert.False, cancellationToken).ConfigureAwait(false)) - { - throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - } - - SetToken(JsonToken.Boolean, isTrue); - return isTrue; - case '/': - await ParseCommentAsync(false, cancellationToken).ConfigureAwait(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) - { - throw CreateUnexpectedCharacterException(currentChar); - } - - // eat - break; - } - } - case State.Finished: - await ReadFinishedAsync(cancellationToken).ConfigureAwait(false); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - /// - /// Asynchronously reads the next JSON token from the source as a []. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the []. This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsBytesAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsBytesAsync(cancellationToken) : base.ReadAsBytesAsync(cancellationToken); - } - - internal async Task DoReadAsBytesAsync(CancellationToken cancellationToken) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - bool isWrapped = false; - - switch (_currentState) - { - case State.PostValue: - if (await ParsePostValueAsync(true, cancellationToken).ConfigureAwait(false)) - { - return null; - } - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - char currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(false)) - { - SetToken(JsonToken.None, null, false); - return null; - } - - break; - case '"': - case '\'': - await ParseStringAsync(currentChar, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(false); - byte[]? data = (byte[]?)Value; - if (isWrapped) - { - await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); - if (TokenType != JsonToken.EndObject) - { - throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); - } - - SetToken(JsonToken.Bytes, data, false); - } - - return data; - case '{': - CharPos++; - SetToken(JsonToken.StartObject); - await ReadIntoWrappedTypeObjectAsync(cancellationToken).ConfigureAwait(false); - isWrapped = true; - break; - case '[': - CharPos++; - SetToken(JsonToken.StartArray); - return await ReadArrayIntoByteArrayAsync(cancellationToken).ConfigureAwait(false); - case 'n': - await HandleNullAsync(cancellationToken).ConfigureAwait(false); - return null; - case '/': - await ParseCommentAsync(false, cancellationToken).ConfigureAwait(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - await ProcessCarriageReturnAsync(false, cancellationToken).ConfigureAwait(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) - { - throw CreateUnexpectedCharacterException(currentChar); - } - - // eat - break; - } - } - case State.Finished: - await ReadFinishedAsync(cancellationToken).ConfigureAwait(false); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private async Task ReadIntoWrappedTypeObjectAsync(CancellationToken cancellationToken) - { - await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); - if (Value != null && Value.ToString() == JsonTypeReflector.TypePropertyName) - { - await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); - if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) - { - await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); - if (Value.ToString() == JsonTypeReflector.ValuePropertyName) - { - return; - } - } - } - - throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsDateTimeAsync(cancellationToken) : base.ReadAsDateTimeAsync(cancellationToken); - } - - internal async Task DoReadAsDateTimeAsync(CancellationToken cancellationToken) - { - return (DateTime?)await ReadStringValueAsync(ReadType.ReadAsDateTime, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsDateTimeOffsetAsync(cancellationToken) : base.ReadAsDateTimeOffsetAsync(cancellationToken); - } - - internal async Task DoReadAsDateTimeOffsetAsync(CancellationToken cancellationToken) - { - return (DateTimeOffset?)await ReadStringValueAsync(ReadType.ReadAsDateTimeOffset, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsDecimalAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsDecimalAsync(cancellationToken) : base.ReadAsDecimalAsync(cancellationToken); - } - - internal async Task DoReadAsDecimalAsync(CancellationToken cancellationToken) - { - return (decimal?)await ReadNumberValueAsync(ReadType.ReadAsDecimal, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsDoubleAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsDoubleAsync(cancellationToken) : base.ReadAsDoubleAsync(cancellationToken); - } - - internal async Task DoReadAsDoubleAsync(CancellationToken cancellationToken) - { - return (double?)await ReadNumberValueAsync(ReadType.ReadAsDouble, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously reads the next JSON token from the source as a of . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the of . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsInt32Async(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsInt32Async(cancellationToken) : base.ReadAsInt32Async(cancellationToken); - } - - internal async Task DoReadAsInt32Async(CancellationToken cancellationToken) - { - return (int?)await ReadNumberValueAsync(ReadType.ReadAsInt32, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously reads the next JSON token from the source as a . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous read. The - /// property returns the . This result will be null at the end of an array. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task ReadAsStringAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoReadAsStringAsync(cancellationToken) : base.ReadAsStringAsync(cancellationToken); - } - - internal async Task DoReadAsStringAsync(CancellationToken cancellationToken) - { - return (string?)await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.cs deleted file mode 100644 index 8f384e1d1..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.cs +++ /dev/null @@ -1,2427 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; -using System.Runtime.CompilerServices; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal enum ReadType - { - Read, - ReadAsInt32, - ReadAsInt64, - ReadAsBytes, - ReadAsString, - ReadAsDecimal, - ReadAsDateTime, -#if HAVE_DATE_TIME_OFFSET - ReadAsDateTimeOffset, -#endif - ReadAsDouble, - ReadAsBoolean - } - - /// - /// Represents a reader that provides fast, non-cached, forward-only access to JSON text data. - /// - internal partial class JsonTextReader : JsonReader, IJsonLineInfo - { - private const char UnicodeReplacementChar = '\uFFFD'; -#if HAVE_BIG_INTEGER - private const int MaximumJavascriptIntegerCharacterLength = 380; -#endif -#if DEBUG - internal int LargeBufferLength { get; set; } = int.MaxValue / 2; -#else - private const int LargeBufferLength = int.MaxValue / 2; -#endif - - private readonly TextReader _reader; - private int _charsUsed; - private int _lineStartPos; - private int _lineNumber; - private bool _isEndOfFile; - private StringBuffer _stringBuffer; - private StringReference _stringReference; - private IArrayPool? _arrayPool; - - /// - /// Initializes a new instance of the class with the specified . - /// - /// The containing the JSON data to read. - public JsonTextReader(TextReader reader) - { - if (reader == null) throw new ArgumentNullException(nameof(reader)); - - _reader = reader; - _lineNumber = 1; - -#if HAVE_ASYNC - _safeAsync = GetType() == typeof(JsonTextReader); -#endif - } - - internal char[]? CharBuffer { get; set; } - - internal int CharPos { get; private set; } - - /// - /// Gets or sets the reader's property name table. - /// - public JsonNameTable? PropertyNameTable { get; set; } - - /// - /// Gets or sets the reader's character buffer pool. - /// - public IArrayPool? ArrayPool - { - get => _arrayPool; - set - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - _arrayPool = value; - } - } - - private void EnsureBufferNotEmpty() - { - if (_stringBuffer.IsEmpty) _stringBuffer = new StringBuffer(_arrayPool, 1024); - } - - private void SetNewLine(bool hasNextChar) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (hasNextChar && CharBuffer[CharPos] == StringUtils.LineFeed) CharPos++; - - OnNewLine(CharPos); - } - - private void OnNewLine(int pos) - { - _lineNumber++; - _lineStartPos = pos; - } - - private void ParseString(char quote, ReadType readType) - { - CharPos++; - - ShiftBufferIfNeeded(); - ReadStringIntoBuffer(quote); - ParseReadString(quote, readType); - } - - private void ParseReadString(char quote, ReadType readType) - { - SetPostValueState(true); - - switch (readType) - { - case ReadType.ReadAsBytes: - Guid g; - byte[] data; - if (_stringReference.Length == 0) - data = CollectionUtils.ArrayEmpty(); - else if (_stringReference.Length == 36 && ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g)) - data = g.ToByteArray(); - else - data = Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length); - - SetToken(JsonToken.Bytes, data, false); - break; - case ReadType.ReadAsString: - var text = _stringReference.ToString(); - - SetToken(JsonToken.String, text, false); - _quoteChar = quote; - break; - case ReadType.ReadAsInt32: - case ReadType.ReadAsDecimal: - case ReadType.ReadAsBoolean: - // caller will convert result - break; - default: - if (_dateParseHandling != DateParseHandling.None) - { - DateParseHandling dateParseHandling; - if (readType == ReadType.ReadAsDateTime) - dateParseHandling = DateParseHandling.DateTime; -#if HAVE_DATE_TIME_OFFSET - else if (readType == ReadType.ReadAsDateTimeOffset) - { - dateParseHandling = DateParseHandling.DateTimeOffset; - } -#endif - else - dateParseHandling = _dateParseHandling; - - if (dateParseHandling == DateParseHandling.DateTime) - { - if (DateTimeUtils.TryParseDateTime(_stringReference, DateTimeZoneHandling, DateFormatString, Culture, out var dt)) - { - SetToken(JsonToken.Date, dt, false); - return; - } - } -#if HAVE_DATE_TIME_OFFSET - else - { - if (DateTimeUtils.TryParseDateTimeOffset(_stringReference, DateFormatString, Culture, out DateTimeOffset dt)) - { - SetToken(JsonToken.Date, dt, false); - return; - } - } -#endif - } - - SetToken(JsonToken.String, _stringReference.ToString(), false); - _quoteChar = quote; - break; - } - } - - private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count) - { - const int charByteCount = 2; - - Buffer.BlockCopy(src, srcOffset * charByteCount, dst, dstOffset * charByteCount, count * charByteCount); - } - - private void ShiftBufferIfNeeded() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // once in the last 10% of the buffer, or buffer is already very large then - // shift the remaining content to the start to avoid unnecessarily increasing - // the buffer size when reading numbers/strings - var length = CharBuffer.Length; - if (length - CharPos <= length * 0.1 || length >= LargeBufferLength) - { - var count = _charsUsed - CharPos; - if (count > 0) BlockCopyChars(CharBuffer, CharPos, CharBuffer, 0, count); - - _lineStartPos -= CharPos; - CharPos = 0; - _charsUsed = count; - CharBuffer[_charsUsed] = '\0'; - } - } - - private int ReadData(bool append) => ReadData(append, 0); - - private void PrepareBufferForReadData(bool append, int charsRequired) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // char buffer is full - if (_charsUsed + charsRequired >= CharBuffer.Length - 1) - { - if (append) - { - var doubledArrayLength = CharBuffer.Length * 2; - - // copy to new array either double the size of the current or big enough to fit required content - var newArrayLength = Math.Max( - doubledArrayLength < 0 ? int.MaxValue : doubledArrayLength, // handle overflow - _charsUsed + charsRequired + 1); - - // increase the size of the buffer - var dst = BufferUtils.RentBuffer(_arrayPool, newArrayLength); - - BlockCopyChars(CharBuffer, 0, dst, 0, CharBuffer.Length); - - BufferUtils.ReturnBuffer(_arrayPool, CharBuffer); - - CharBuffer = dst; - } - else - { - var remainingCharCount = _charsUsed - CharPos; - - if (remainingCharCount + charsRequired + 1 >= CharBuffer.Length) - { - // the remaining count plus the required is bigger than the current buffer size - var dst = BufferUtils.RentBuffer(_arrayPool, remainingCharCount + charsRequired + 1); - - if (remainingCharCount > 0) BlockCopyChars(CharBuffer, CharPos, dst, 0, remainingCharCount); - - BufferUtils.ReturnBuffer(_arrayPool, CharBuffer); - - CharBuffer = dst; - } - else - { - // copy any remaining data to the beginning of the buffer if needed and reset positions - if (remainingCharCount > 0) BlockCopyChars(CharBuffer, CharPos, CharBuffer, 0, remainingCharCount); - } - - _lineStartPos -= CharPos; - CharPos = 0; - _charsUsed = remainingCharCount; - } - } - } - - private int ReadData(bool append, int charsRequired) - { - if (_isEndOfFile) return 0; - - PrepareBufferForReadData(append, charsRequired); - MiscellaneousUtils.Assert(CharBuffer != null); - - var attemptCharReadCount = CharBuffer.Length - _charsUsed - 1; - - var charsRead = _reader.Read(CharBuffer, _charsUsed, attemptCharReadCount); - - _charsUsed += charsRead; - - if (charsRead == 0) _isEndOfFile = true; - - CharBuffer[_charsUsed] = '\0'; - return charsRead; - } - - private bool EnsureChars(int relativePosition, bool append) - { - if (CharPos + relativePosition >= _charsUsed) return ReadChars(relativePosition, append); - - return true; - } - - private bool ReadChars(int relativePosition, bool append) - { - if (_isEndOfFile) return false; - - var charsRequired = CharPos + relativePosition - _charsUsed + 1; - - var totalCharsRead = 0; - - // it is possible that the TextReader doesn't return all data at once - // repeat read until the required text is returned or the reader is out of content - do - { - var charsRead = ReadData(append, charsRequired - totalCharsRead); - - // no more content - if (charsRead == 0) break; - - totalCharsRead += charsRead; - } while (totalCharsRead < charsRequired); - - if (totalCharsRead < charsRequired) return false; - - return true; - } - - /// - /// Reads the next JSON token from the underlying . - /// - /// - /// true if the next token was read successfully; false if there are no more tokens to read. - /// - public override bool Read() - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - switch (_currentState) - { - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - return ParseValue(); - case State.Object: - case State.ObjectStart: - return ParseObject(); - case State.PostValue: - // returns true if it hits - // end of object or array - if (ParsePostValue(false)) return true; - - break; - case State.Finished: - if (EnsureChars(0, false)) - { - EatWhitespace(); - if (_isEndOfFile) - { - SetToken(JsonToken.None); - return false; - } - if (CharBuffer[CharPos] == '/') - { - ParseComment(true); - return true; - } - - throw JsonReaderException.Create(this, - "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, - CharBuffer[CharPos])); - } - SetToken(JsonToken.None); - return false; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override int? ReadAsInt32() => (int?)ReadNumberValue(ReadType.ReadAsInt32); - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override DateTime? ReadAsDateTime() => (DateTime?)ReadStringValue(ReadType.ReadAsDateTime); - - /// - /// Reads the next JSON token from the underlying as a . - /// - /// A . This method will return null at the end of an array. - public override string? ReadAsString() => (string?)ReadStringValue(ReadType.ReadAsString); - - /// - /// Reads the next JSON token from the underlying as a []. - /// - /// - /// A [] or null if the next JSON token is null. This method will return null at - /// the end of an array. - /// - public override byte[]? ReadAsBytes() - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - var isWrapped = false; - - switch (_currentState) - { - case State.PostValue: - if (ParsePostValue(true)) return null; - - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (ReadNullChar()) - { - SetToken(JsonToken.None, null, false); - return null; - } - break; - case '"': - case '\'': - ParseString(currentChar, ReadType.ReadAsBytes); - var data = (byte[]?)Value; - if (isWrapped) - { - ReaderReadAndAssert(); - if (TokenType != JsonToken.EndObject) - throw JsonReaderException.Create(this, - "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); - - SetToken(JsonToken.Bytes, data, false); - } - return data; - case '{': - CharPos++; - SetToken(JsonToken.StartObject); - ReadIntoWrappedTypeObject(); - isWrapped = true; - break; - case '[': - CharPos++; - SetToken(JsonToken.StartArray); - return ReadArrayIntoByteArray(); - case 'n': - HandleNull(); - return null; - case '/': - ParseComment(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) throw CreateUnexpectedCharacterException(currentChar); - - // eat - break; - } - } - case State.Finished: - ReadFinished(); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private object? ReadStringValue(ReadType readType) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (ParsePostValue(true)) return null; - - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (ReadNullChar()) - { - SetToken(JsonToken.None, null, false); - return null; - } - break; - case '"': - case '\'': - ParseString(currentChar, readType); - return FinishReadQuotedStringValue(readType); - case '-': - if (EnsureChars(1, true) && CharBuffer[CharPos + 1] == 'I') - return ParseNumberNegativeInfinity(readType); - else - { - ParseNumber(readType); - return Value; - } - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (readType != ReadType.ReadAsString) - { - CharPos++; - throw CreateUnexpectedCharacterException(currentChar); - } - ParseNumber(ReadType.ReadAsString); - return Value; - case 't': - case 'f': - if (readType != ReadType.ReadAsString) - { - CharPos++; - throw CreateUnexpectedCharacterException(currentChar); - } - var expected = currentChar == 't' ? JsonConvert.True : JsonConvert.False; - if (!MatchValueWithTrailingSeparator(expected)) throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - - SetToken(JsonToken.String, expected); - return expected; - case 'I': - return ParseNumberPositiveInfinity(readType); - case 'N': - return ParseNumberNaN(readType); - case 'n': - HandleNull(); - return null; - case '/': - ParseComment(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) throw CreateUnexpectedCharacterException(currentChar); - - // eat - break; - } - } - case State.Finished: - ReadFinished(); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private object? FinishReadQuotedStringValue(ReadType readType) - { - switch (readType) - { - case ReadType.ReadAsBytes: - case ReadType.ReadAsString: - return Value; - case ReadType.ReadAsDateTime: - if (Value is DateTime time) return time; - - return ReadDateTimeString((string?)Value); -#if HAVE_DATE_TIME_OFFSET - case ReadType.ReadAsDateTimeOffset: - if (Value is DateTimeOffset offset) - { - return offset; - } - - return ReadDateTimeOffsetString((string?)Value); -#endif - default: - throw new ArgumentOutOfRangeException(nameof(readType)); - } - } - - private JsonReaderException CreateUnexpectedCharacterException(char c) => JsonReaderException.Create(this, - "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override bool? ReadAsBoolean() - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (ParsePostValue(true)) return null; - - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (ReadNullChar()) - { - SetToken(JsonToken.None, null, false); - return null; - } - break; - case '"': - case '\'': - ParseString(currentChar, ReadType.Read); - return ReadBooleanString(_stringReference.ToString()); - case 'n': - HandleNull(); - return null; - case '-': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - ParseNumber(ReadType.Read); - bool b; -#if HAVE_BIG_INTEGER - if (Value is BigInteger integer) - { - b = integer != 0; - } - else -#endif - { - b = Convert.ToBoolean(Value, CultureInfo.InvariantCulture); - } - SetToken(JsonToken.Boolean, b, false); - return b; - case 't': - case 'f': - var isTrue = currentChar == 't'; - var expected = isTrue ? JsonConvert.True : JsonConvert.False; - - if (!MatchValueWithTrailingSeparator(expected)) throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - - SetToken(JsonToken.Boolean, isTrue); - return isTrue; - case '/': - ParseComment(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) throw CreateUnexpectedCharacterException(currentChar); - - // eat - break; - } - } - case State.Finished: - ReadFinished(); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private void ProcessValueComma() - { - CharPos++; - - if (_currentState != State.PostValue) - { - SetToken(JsonToken.Undefined); - var ex = CreateUnexpectedCharacterException(','); - // so the comma will be parsed again - CharPos--; - - throw ex; - } - - SetStateBasedOnCurrent(); - } - - private object? ReadNumberValue(ReadType readType) - { - EnsureBuffer(); - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (_currentState) - { - case State.PostValue: - if (ParsePostValue(true)) return null; - - goto case State.Start; - case State.Start: - case State.Property: - case State.Array: - case State.ArrayStart: - case State.Constructor: - case State.ConstructorStart: - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (ReadNullChar()) - { - SetToken(JsonToken.None, null, false); - return null; - } - break; - case '"': - case '\'': - ParseString(currentChar, readType); - return FinishReadQuotedNumber(readType); - case 'n': - HandleNull(); - return null; - case 'N': - return ParseNumberNaN(readType); - case 'I': - return ParseNumberPositiveInfinity(readType); - case '-': - if (EnsureChars(1, true) && CharBuffer[CharPos + 1] == 'I') - return ParseNumberNegativeInfinity(readType); - else - { - ParseNumber(readType); - return Value; - } - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - ParseNumber(readType); - return Value; - case '/': - ParseComment(false); - break; - case ',': - ProcessValueComma(); - break; - case ']': - CharPos++; - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) - { - SetToken(JsonToken.EndArray); - return null; - } - throw CreateUnexpectedCharacterException(currentChar); - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - CharPos++; - - if (!char.IsWhiteSpace(currentChar)) throw CreateUnexpectedCharacterException(currentChar); - - // eat - break; - } - } - case State.Finished: - ReadFinished(); - return null; - default: - throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState)); - } - } - - private object? FinishReadQuotedNumber(ReadType readType) - { - switch (readType) - { - case ReadType.ReadAsInt32: - return ReadInt32String(_stringReference.ToString()); - case ReadType.ReadAsDecimal: - return ReadDecimalString(_stringReference.ToString()); - case ReadType.ReadAsDouble: - return ReadDoubleString(_stringReference.ToString()); - default: - throw new ArgumentOutOfRangeException(nameof(readType)); - } - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Reads the next JSON token from the underlying as a of . - /// - /// A of . This method will return null at the end of an array. - public override DateTimeOffset? ReadAsDateTimeOffset() - { - return (DateTimeOffset?)ReadStringValue(ReadType.ReadAsDateTimeOffset); - } -#endif - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override decimal? ReadAsDecimal() => (decimal?)ReadNumberValue(ReadType.ReadAsDecimal); - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override double? ReadAsDouble() => (double?)ReadNumberValue(ReadType.ReadAsDouble); - - private void HandleNull() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (EnsureChars(1, true)) - { - var next = CharBuffer[CharPos + 1]; - - if (next == 'u') - { - ParseNull(); - return; - } - - CharPos += 2; - throw CreateUnexpectedCharacterException(CharBuffer[CharPos - 1]); - } - - CharPos = _charsUsed; - throw CreateUnexpectedEndException(); - } - - private void ReadFinished() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (EnsureChars(0, false)) - { - EatWhitespace(); - if (_isEndOfFile) return; - - if (CharBuffer[CharPos] == '/') - ParseComment(false); - else - throw JsonReaderException.Create(this, - "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, - CharBuffer[CharPos])); - } - - SetToken(JsonToken.None); - } - - private bool ReadNullChar() - { - if (_charsUsed == CharPos) - { - if (ReadData(false) == 0) - { - _isEndOfFile = true; - return true; - } - } - else - CharPos++; - - return false; - } - - private void EnsureBuffer() - { - if (CharBuffer == null) - { - CharBuffer = BufferUtils.RentBuffer(_arrayPool, 1024); - CharBuffer[0] = '\0'; - } - } - - private void ReadStringIntoBuffer(char quote) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - var charPos = CharPos; - var initialPosition = CharPos; - var lastWritePosition = CharPos; - _stringBuffer.Position = 0; - - while (true) - { - switch (CharBuffer[charPos++]) - { - case '\0': - if (_charsUsed == charPos - 1) - { - charPos--; - - if (ReadData(true) == 0) - { - CharPos = charPos; - throw JsonReaderException.Create(this, - "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); - } - } - break; - case '\\': - CharPos = charPos; - if (!EnsureChars(0, true)) - throw JsonReaderException.Create(this, - "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); - - // start of escape sequence - var escapeStartPos = charPos - 1; - - var currentChar = CharBuffer[charPos]; - charPos++; - - char writeChar; - - switch (currentChar) - { - case 'b': - writeChar = '\b'; - break; - case 't': - writeChar = '\t'; - break; - case 'n': - writeChar = '\n'; - break; - case 'f': - writeChar = '\f'; - break; - case 'r': - writeChar = '\r'; - break; - case '\\': - writeChar = '\\'; - break; - case '"': - case '\'': - case '/': - writeChar = currentChar; - break; - case 'u': - CharPos = charPos; - writeChar = ParseUnicode(); - - if (StringUtils.IsLowSurrogate(writeChar)) - { - // low surrogate with no preceding high surrogate; this char is replaced - writeChar = UnicodeReplacementChar; - } - else if (StringUtils.IsHighSurrogate(writeChar)) - { - bool anotherHighSurrogate; - - // loop for handling situations where there are multiple consecutive high surrogates - do - { - anotherHighSurrogate = false; - - // potential start of a surrogate pair - if (EnsureChars(2, true) && CharBuffer[CharPos] == '\\' && CharBuffer[CharPos + 1] == 'u') - { - var highSurrogate = writeChar; - - CharPos += 2; - writeChar = ParseUnicode(); - - if (StringUtils.IsLowSurrogate(writeChar)) - { - // a valid surrogate pair! - } - else if (StringUtils.IsHighSurrogate(writeChar)) - { - // another high surrogate; replace current and start check over - highSurrogate = UnicodeReplacementChar; - anotherHighSurrogate = true; - } - else - { - // high surrogate not followed by low surrogate; original char is replaced - highSurrogate = UnicodeReplacementChar; - } - - EnsureBufferNotEmpty(); - - WriteCharToBuffer(highSurrogate, lastWritePosition, escapeStartPos); - lastWritePosition = CharPos; - } - else - { - // there are not enough remaining chars for the low surrogate or is not follow by unicode sequence - // replace high surrogate and continue on as usual - writeChar = UnicodeReplacementChar; - } - } while (anotherHighSurrogate); - } - - charPos = CharPos; - break; - default: - CharPos = charPos; - throw JsonReaderException.Create(this, - "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar)); - } - - EnsureBufferNotEmpty(); - WriteCharToBuffer(writeChar, lastWritePosition, escapeStartPos); - - lastWritePosition = charPos; - break; - case StringUtils.CarriageReturn: - CharPos = charPos - 1; - ProcessCarriageReturn(true); - charPos = CharPos; - break; - case StringUtils.LineFeed: - CharPos = charPos - 1; - ProcessLineFeed(); - charPos = CharPos; - break; - case '"': - case '\'': - if (CharBuffer[charPos - 1] == quote) - { - FinishReadStringIntoBuffer(charPos - 1, initialPosition, lastWritePosition); - return; - } - break; - } - } - } - - private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (initialPosition == lastWritePosition) - _stringReference = new StringReference(CharBuffer, initialPosition, charPos - initialPosition); - else - { - EnsureBufferNotEmpty(); - - if (charPos > lastWritePosition) _stringBuffer.Append(_arrayPool, CharBuffer, lastWritePosition, charPos - lastWritePosition); - - _stringReference = new StringReference(_stringBuffer.InternalBuffer!, 0, _stringBuffer.Position); - } - - CharPos = charPos + 1; - } - - private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (writeToPosition > lastWritePosition) - _stringBuffer.Append(_arrayPool, CharBuffer, lastWritePosition, writeToPosition - lastWritePosition); - - _stringBuffer.Append(_arrayPool, writeChar); - } - - private char ConvertUnicode(bool enoughChars) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (enoughChars) - { - if (ConvertUtils.TryHexTextToInt(CharBuffer, CharPos, CharPos + 4, out var value)) - { - var hexChar = Convert.ToChar(value); - CharPos += 4; - return hexChar; - } - throw JsonReaderException.Create(this, - @"Invalid Unicode escape sequence: \u{0}.".FormatWith(CultureInfo.InvariantCulture, new string(CharBuffer, CharPos, 4))); - } - throw JsonReaderException.Create(this, "Unexpected end while parsing Unicode escape sequence."); - } - - private char ParseUnicode() => ConvertUnicode(EnsureChars(4, true)); - - private void ReadNumberIntoBuffer() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - var charPos = CharPos; - - while (true) - { - var currentChar = CharBuffer[charPos]; - if (currentChar == '\0') - { - CharPos = charPos; - - if (_charsUsed == charPos) - { - if (ReadData(true) == 0) return; - } - else - return; - } - else if (ReadNumberCharIntoBuffer(currentChar, charPos)) - return; - else - charPos++; - } - } - - private bool ReadNumberCharIntoBuffer(char currentChar, int charPos) - { - switch (currentChar) - { - case '-': - case '+': - case 'a': - case 'A': - case 'b': - case 'B': - case 'c': - case 'C': - case 'd': - case 'D': - case 'e': - case 'E': - case 'f': - case 'F': - case 'x': - case 'X': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return false; - default: - CharPos = charPos; - - if (char.IsWhiteSpace(currentChar) || currentChar == ',' || currentChar == '}' || currentChar == ']' || currentChar == ')' - || currentChar == '/') return true; - - throw JsonReaderException.Create(this, - "Unexpected character encountered while parsing number: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); - } - } - - private void ClearRecentString() - { - _stringBuffer.Position = 0; - _stringReference = new StringReference(); - } - - private bool ParsePostValue(bool ignoreComments) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (ReadData(false) == 0) - { - _currentState = State.Finished; - return false; - } - } - else - CharPos++; - break; - case '}': - CharPos++; - SetToken(JsonToken.EndObject); - return true; - case ']': - CharPos++; - SetToken(JsonToken.EndArray); - return true; - case ')': - CharPos++; - SetToken(JsonToken.EndConstructor); - return true; - case '/': - ParseComment(!ignoreComments); - if (!ignoreComments) return true; - - break; - case ',': - CharPos++; - - // finished parsing - SetStateBasedOnCurrent(); - return false; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - } - else - { - // handle multiple content without comma delimiter - if (SupportMultipleContent && Depth == 0) - { - SetStateBasedOnCurrent(); - return false; - } - - throw JsonReaderException.Create(this, - "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, - currentChar)); - } - break; - } - } - } - - private bool ParseObject() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (ReadData(false) == 0) return false; - } - else - CharPos++; - break; - case '}': - SetToken(JsonToken.EndObject); - CharPos++; - return true; - case '/': - ParseComment(true); - return true; - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - } - else - return ParseProperty(); - - break; - } - } - } - - private bool ParseProperty() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - var firstChar = CharBuffer[CharPos]; - char quoteChar; - - if (firstChar == '"' || firstChar == '\'') - { - CharPos++; - quoteChar = firstChar; - ShiftBufferIfNeeded(); - ReadStringIntoBuffer(quoteChar); - } - else if (ValidIdentifierChar(firstChar)) - { - quoteChar = '\0'; - ShiftBufferIfNeeded(); - ParseUnquotedProperty(); - } - else - throw JsonReaderException.Create(this, - "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - - string? propertyName; - - if (PropertyNameTable != null) - { - propertyName = PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length); - - // no match in name table - if (propertyName == null) propertyName = _stringReference.ToString(); - } - else - propertyName = _stringReference.ToString(); - - EatWhitespace(); - - if (CharBuffer[CharPos] != ':') - throw JsonReaderException.Create(this, - "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, - CharBuffer[CharPos])); - - CharPos++; - - SetToken(JsonToken.PropertyName, propertyName); - _quoteChar = quoteChar; - ClearRecentString(); - - return true; - } - - private bool ValidIdentifierChar(char value) => char.IsLetterOrDigit(value) || value == '_' || value == '$'; - - private void ParseUnquotedProperty() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - var initialPosition = CharPos; - - // parse unquoted property name until whitespace or colon - while (true) - { - var currentChar = CharBuffer[CharPos]; - if (currentChar == '\0') - { - if (_charsUsed == CharPos) - { - if (ReadData(true) == 0) throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); - - continue; - } - - _stringReference = new StringReference(CharBuffer, initialPosition, CharPos - initialPosition); - return; - } - - if (ReadUnquotedPropertyReportIfDone(currentChar, initialPosition)) return; - } - } - - private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (ValidIdentifierChar(currentChar)) - { - CharPos++; - return false; - } - - if (char.IsWhiteSpace(currentChar) || currentChar == ':') - { - _stringReference = new StringReference(CharBuffer, initialPosition, CharPos - initialPosition); - return true; - } - - throw JsonReaderException.Create(this, - "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); - } - - private bool ParseValue() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (ReadData(false) == 0) return false; - } - else - CharPos++; - break; - case '"': - case '\'': - ParseString(currentChar, ReadType.Read); - return true; - case 't': - ParseTrue(); - return true; - case 'f': - ParseFalse(); - return true; - case 'n': - if (EnsureChars(1, true)) - { - var next = CharBuffer[CharPos + 1]; - - if (next == 'u') - ParseNull(); - else if (next == 'e') - ParseConstructor(); - else - throw CreateUnexpectedCharacterException(CharBuffer[CharPos]); - } - else - { - CharPos++; - throw CreateUnexpectedEndException(); - } - return true; - case 'N': - ParseNumberNaN(ReadType.Read); - return true; - case 'I': - ParseNumberPositiveInfinity(ReadType.Read); - return true; - case '-': - if (EnsureChars(1, true) && CharBuffer[CharPos + 1] == 'I') - ParseNumberNegativeInfinity(ReadType.Read); - else - ParseNumber(ReadType.Read); - return true; - case '/': - ParseComment(true); - return true; - case 'u': - ParseUndefined(); - return true; - case '{': - CharPos++; - SetToken(JsonToken.StartObject); - return true; - case '[': - CharPos++; - SetToken(JsonToken.StartArray); - return true; - case ']': - CharPos++; - SetToken(JsonToken.EndArray); - return true; - case ',': - // don't increment position, the next call to read will handle comma - // this is done to handle multiple empty comma values - SetToken(JsonToken.Undefined); - return true; - case ')': - CharPos++; - SetToken(JsonToken.EndConstructor); - return true; - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - case ' ': - case StringUtils.Tab: - // eat - CharPos++; - break; - default: - if (char.IsWhiteSpace(currentChar)) - { - // eat - CharPos++; - break; - } - if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.') - { - ParseNumber(ReadType.Read); - return true; - } - - throw CreateUnexpectedCharacterException(currentChar); - } - } - } - - private void ProcessLineFeed() - { - CharPos++; - OnNewLine(CharPos); - } - - private void ProcessCarriageReturn(bool append) - { - CharPos++; - - SetNewLine(EnsureChars(1, append)); - } - - private void EatWhitespace() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - while (true) - { - var currentChar = CharBuffer[CharPos]; - - switch (currentChar) - { - case '\0': - if (_charsUsed == CharPos) - { - if (ReadData(false) == 0) return; - } - else - CharPos++; - break; - case StringUtils.CarriageReturn: - ProcessCarriageReturn(false); - break; - case StringUtils.LineFeed: - ProcessLineFeed(); - break; - default: - if (currentChar == ' ' || char.IsWhiteSpace(currentChar)) - CharPos++; - else - return; - - break; - } - } - } - - private void ParseConstructor() - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (MatchValueWithTrailingSeparator("new")) - { - EatWhitespace(); - - var initialPosition = CharPos; - int endPosition; - - while (true) - { - var currentChar = CharBuffer[CharPos]; - if (currentChar == '\0') - { - if (_charsUsed == CharPos) - { - if (ReadData(true) == 0) throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); - } - else - { - endPosition = CharPos; - CharPos++; - break; - } - } - else if (char.IsLetterOrDigit(currentChar)) - CharPos++; - else if (currentChar == StringUtils.CarriageReturn) - { - endPosition = CharPos; - ProcessCarriageReturn(true); - break; - } - else if (currentChar == StringUtils.LineFeed) - { - endPosition = CharPos; - ProcessLineFeed(); - break; - } - else if (char.IsWhiteSpace(currentChar)) - { - endPosition = CharPos; - CharPos++; - break; - } - else if (currentChar == '(') - { - endPosition = CharPos; - break; - } - else - throw JsonReaderException.Create(this, - "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); - } - - _stringReference = new StringReference(CharBuffer, initialPosition, endPosition - initialPosition); - var constructorName = _stringReference.ToString(); - - EatWhitespace(); - - if (CharBuffer[CharPos] != '(') - throw JsonReaderException.Create(this, - "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - - CharPos++; - - ClearRecentString(); - - SetToken(JsonToken.StartConstructor, constructorName); - } - else - throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); - } - - private void ParseNumber(ReadType readType) - { - ShiftBufferIfNeeded(); - MiscellaneousUtils.Assert(CharBuffer != null); - - var firstChar = CharBuffer[CharPos]; - var initialPosition = CharPos; - - ReadNumberIntoBuffer(); - - ParseReadNumber(readType, firstChar, initialPosition); - } - - private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // set state to PostValue now so that if there is an error parsing the number then the reader can continue - SetPostValueState(true); - - _stringReference = new StringReference(CharBuffer, initialPosition, CharPos - initialPosition); - - object numberValue; - JsonToken numberType; - - var singleDigit = char.IsDigit(firstChar) && _stringReference.Length == 1; - var nonBase10 = firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.' - && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E'; - - switch (readType) - { - case ReadType.ReadAsString: - { - var number = _stringReference.ToString(); - - // validate that the string is a valid number - if (nonBase10) - { - try - { - if (number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) - Convert.ToInt64(number, 16); - else - Convert.ToInt64(number, 8); - } - catch (Exception ex) - { - throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, number), ex); - } - } - else - { - if (!double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out _)) - throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - - numberType = JsonToken.String; - numberValue = number; - } - break; - case ReadType.ReadAsInt32: - { - if (singleDigit) - { - // digit char values start at 48 - numberValue = firstChar - 48; - } - else if (nonBase10) - { - var number = _stringReference.ToString(); - - try - { - var integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) - ? Convert.ToInt32(number, 16) - : Convert.ToInt32(number, 8); - - numberValue = integer; - } - catch (Exception ex) - { - throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, number), ex); - } - } - else - { - var parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, - out var value); - if (parseResult == ParseResult.Success) - numberValue = value; - else if (parseResult == ParseResult.Overflow) - throw ThrowReaderError( - "JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - else - throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - - numberType = JsonToken.Integer; - } - break; - case ReadType.ReadAsDecimal: - { - if (singleDigit) - { - // digit char values start at 48 - numberValue = (decimal)firstChar - 48; - } - else if (nonBase10) - { - var number = _stringReference.ToString(); - - try - { - // decimal.Parse doesn't support parsing hexadecimal values - var integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) - ? Convert.ToInt64(number, 16) - : Convert.ToInt64(number, 8); - - numberValue = Convert.ToDecimal(integer); - } - catch (Exception ex) - { - throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, number), ex); - } - } - else - { - var parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, - out var value); - if (parseResult == ParseResult.Success) - numberValue = value; - else - throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - - numberType = JsonToken.Float; - } - break; - case ReadType.ReadAsDouble: - { - if (singleDigit) - { - // digit char values start at 48 - numberValue = (double)firstChar - 48; - } - else if (nonBase10) - { - var number = _stringReference.ToString(); - - try - { - // double.Parse doesn't support parsing hexadecimal values - var integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) - ? Convert.ToInt64(number, 16) - : Convert.ToInt64(number, 8); - - numberValue = Convert.ToDouble(integer); - } - catch (Exception ex) - { - throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, number), ex); - } - } - else - { - var number = _stringReference.ToString(); - - if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)) - numberValue = value; - else - throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - - numberType = JsonToken.Float; - } - break; - case ReadType.Read: - case ReadType.ReadAsInt64: - { - if (singleDigit) - { - // digit char values start at 48 - numberValue = (long)firstChar - 48; - numberType = JsonToken.Integer; - } - else if (nonBase10) - { - var number = _stringReference.ToString(); - - try - { - numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) - ? Convert.ToInt64(number, 16) - : Convert.ToInt64(number, 8); - } - catch (Exception ex) - { - throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, number), ex); - } - - numberType = JsonToken.Integer; - } - else - { - var parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, - out var value); - if (parseResult == ParseResult.Success) - { - numberValue = value; - numberType = JsonToken.Integer; - } - else if (parseResult == ParseResult.Overflow) - { -#if HAVE_BIG_INTEGER - string number = _stringReference.ToString(); - - if (number.Length > MaximumJavascriptIntegerCharacterLength) - { - throw ThrowReaderError("JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); - } - - numberValue = BigIntegerParse(number, CultureInfo.InvariantCulture); - numberType = JsonToken.Integer; -#else - throw ThrowReaderError( - "JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); -#endif - } - else - { - if (_floatParseHandling == FloatParseHandling.Decimal) - { - parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, - _stringReference.Length, out var d); - if (parseResult == ParseResult.Success) - numberValue = d; - else - throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - else - { - var number = _stringReference.ToString(); - - if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out var d)) - numberValue = d; - else - throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, - _stringReference.ToString())); - } - - numberType = JsonToken.Float; - } - } - } - break; - default: - throw JsonReaderException.Create(this, "Cannot read number value as type."); - } - - ClearRecentString(); - - // index has already been updated - SetToken(numberType, numberValue, false); - } - - private JsonReaderException ThrowReaderError(string message, Exception? ex = null) - { - SetToken(JsonToken.Undefined, null, false); - return JsonReaderException.Create(this, message, ex); - } - -#if HAVE_BIG_INTEGER - // By using the BigInteger type in a separate method, - // the runtime can execute the ParseNumber even if - // the System.Numerics.BigInteger.Parse method is - // missing, which happens in some versions of Mono - [MethodImpl(MethodImplOptions.NoInlining)] - private static object BigIntegerParse(string number, CultureInfo culture) - { - return System.Numerics.BigInteger.Parse(number, culture); - } -#endif - - private void ParseComment(bool setToken) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // should have already parsed / character before reaching this method - CharPos++; - - if (!EnsureChars(1, false)) throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); - - bool singlelineComment; - - if (CharBuffer[CharPos] == '*') - singlelineComment = false; - else if (CharBuffer[CharPos] == '/') - singlelineComment = true; - else - throw JsonReaderException.Create(this, - "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, CharBuffer[CharPos])); - - CharPos++; - - var initialPosition = CharPos; - - while (true) - { - switch (CharBuffer[CharPos]) - { - case '\0': - if (_charsUsed == CharPos) - { - if (ReadData(true) == 0) - { - if (!singlelineComment) throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); - - EndComment(setToken, initialPosition, CharPos); - return; - } - } - else - CharPos++; - break; - case '*': - CharPos++; - - if (!singlelineComment) - { - if (EnsureChars(0, true)) - { - if (CharBuffer[CharPos] == '/') - { - EndComment(setToken, initialPosition, CharPos - 1); - - CharPos++; - return; - } - } - } - break; - case StringUtils.CarriageReturn: - if (singlelineComment) - { - EndComment(setToken, initialPosition, CharPos); - return; - } - ProcessCarriageReturn(true); - break; - case StringUtils.LineFeed: - if (singlelineComment) - { - EndComment(setToken, initialPosition, CharPos); - return; - } - ProcessLineFeed(); - break; - default: - CharPos++; - break; - } - } - } - - private void EndComment(bool setToken, int initialPosition, int endPosition) - { - if (setToken) SetToken(JsonToken.Comment, new string(CharBuffer, initialPosition, endPosition - initialPosition)); - } - - private bool MatchValue(string value) => MatchValue(EnsureChars(value.Length - 1, true), value); - - private bool MatchValue(bool enoughChars, string value) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - if (!enoughChars) - { - CharPos = _charsUsed; - throw CreateUnexpectedEndException(); - } - - for (var i = 0; i < value.Length; i++) - { - if (CharBuffer[CharPos + i] != value[i]) - { - CharPos += i; - return false; - } - } - - CharPos += value.Length; - - return true; - } - - private bool MatchValueWithTrailingSeparator(string value) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - // will match value and then move to the next character, checking that it is a separator character - var match = MatchValue(value); - - if (!match) return false; - - if (!EnsureChars(0, false)) return true; - - return IsSeparator(CharBuffer[CharPos]) || CharBuffer[CharPos] == '\0'; - } - - private bool IsSeparator(char c) - { - MiscellaneousUtils.Assert(CharBuffer != null); - - switch (c) - { - case '}': - case ']': - case ',': - return true; - case '/': - // check next character to see if start of a comment - if (!EnsureChars(1, false)) return false; - - var nextChart = CharBuffer[CharPos + 1]; - - return nextChart == '*' || nextChart == '/'; - case ')': - if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart) return true; - - break; - case ' ': - case StringUtils.Tab: - case StringUtils.LineFeed: - case StringUtils.CarriageReturn: - return true; - default: - if (char.IsWhiteSpace(c)) return true; - - break; - } - - return false; - } - - private void ParseTrue() - { - // check characters equal 'true' - // and that it is followed by either a separator character - // or the text ends - if (MatchValueWithTrailingSeparator(JsonConvert.True)) - SetToken(JsonToken.Boolean, true); - else - throw JsonReaderException.Create(this, "Error parsing boolean value."); - } - - private void ParseNull() - { - if (MatchValueWithTrailingSeparator(JsonConvert.Null)) - SetToken(JsonToken.Null); - else - throw JsonReaderException.Create(this, "Error parsing null value."); - } - - private void ParseUndefined() - { - if (MatchValueWithTrailingSeparator(JsonConvert.Undefined)) - SetToken(JsonToken.Undefined); - else - throw JsonReaderException.Create(this, "Error parsing undefined value."); - } - - private void ParseFalse() - { - if (MatchValueWithTrailingSeparator(JsonConvert.False)) - SetToken(JsonToken.Boolean, false); - else - throw JsonReaderException.Create(this, "Error parsing boolean value."); - } - - private object ParseNumberNegativeInfinity(ReadType readType) => - ParseNumberNegativeInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity)); - - private object ParseNumberNegativeInfinity(ReadType readType, bool matched) - { - if (matched) - { - switch (readType) - { - case ReadType.Read: - case ReadType.ReadAsDouble: - if (_floatParseHandling == FloatParseHandling.Double) - { - SetToken(JsonToken.Float, double.NegativeInfinity); - return double.NegativeInfinity; - } - break; - case ReadType.ReadAsString: - SetToken(JsonToken.String, JsonConvert.NegativeInfinity); - return JsonConvert.NegativeInfinity; - } - - throw JsonReaderException.Create(this, "Cannot read -Infinity value."); - } - - throw JsonReaderException.Create(this, "Error parsing -Infinity value."); - } - - private object ParseNumberPositiveInfinity(ReadType readType) => - ParseNumberPositiveInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity)); - - private object ParseNumberPositiveInfinity(ReadType readType, bool matched) - { - if (matched) - { - switch (readType) - { - case ReadType.Read: - case ReadType.ReadAsDouble: - if (_floatParseHandling == FloatParseHandling.Double) - { - SetToken(JsonToken.Float, double.PositiveInfinity); - return double.PositiveInfinity; - } - break; - case ReadType.ReadAsString: - SetToken(JsonToken.String, JsonConvert.PositiveInfinity); - return JsonConvert.PositiveInfinity; - } - - throw JsonReaderException.Create(this, "Cannot read Infinity value."); - } - - throw JsonReaderException.Create(this, "Error parsing Infinity value."); - } - - private object ParseNumberNaN(ReadType readType) => ParseNumberNaN(readType, MatchValueWithTrailingSeparator(JsonConvert.NaN)); - - private object ParseNumberNaN(ReadType readType, bool matched) - { - if (matched) - { - switch (readType) - { - case ReadType.Read: - case ReadType.ReadAsDouble: - if (_floatParseHandling == FloatParseHandling.Double) - { - SetToken(JsonToken.Float, double.NaN); - return double.NaN; - } - break; - case ReadType.ReadAsString: - SetToken(JsonToken.String, JsonConvert.NaN); - return JsonConvert.NaN; - } - - throw JsonReaderException.Create(this, "Cannot read NaN value."); - } - - throw JsonReaderException.Create(this, "Error parsing NaN value."); - } - - /// - /// Changes the reader's state to . - /// If is set to true, the underlying is also closed. - /// - public override void Close() - { - base.Close(); - - if (CharBuffer != null) - { - BufferUtils.ReturnBuffer(_arrayPool, CharBuffer); - CharBuffer = null; - } - - if (CloseInput) - { -#if HAVE_STREAM_READER_WRITER_CLOSE - _reader?.Close(); -#else - _reader?.Dispose(); -#endif - } - - _stringBuffer.Clear(_arrayPool); - } - - /// - /// Gets a value indicating whether the class can return line information. - /// - /// - /// true if and can be - /// provided; otherwise, false. - /// - public bool HasLineInfo() => true; - - /// - /// Gets the current line number. - /// - /// - /// The current line number or 0 if no line information is available (for example, - /// returns false). - /// - public int LineNumber - { - get - { - if (CurrentState == State.Start && LinePosition == 0 && TokenType != JsonToken.Comment) return 0; - - return _lineNumber; - } - } - - /// - /// Gets the current line position. - /// - /// - /// The current line position or 0 if no line information is available (for example, - /// returns false). - /// - public int LinePosition => CharPos - _lineStartPos; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.Async.cs deleted file mode 100644 index 65e60d12d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.Async.cs +++ /dev/null @@ -1,1362 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -using System.Threading; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal partial class JsonTextWriter - { - // It's not safe to perform the async methods here in a derived class as if the synchronous equivalent - // has been overriden then the asychronous method will no longer be doing the same operation. -#if HAVE_ASYNC // Double-check this isn't included inappropriately. - private readonly bool _safeAsync; -#endif - - /// - /// Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task FlushAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoFlushAsync(cancellationToken) : base.FlushAsync(cancellationToken); - } - - internal Task DoFlushAsync(CancellationToken cancellationToken) - { - return cancellationToken.CancelIfRequestedAsync() ?? _writer.FlushAsync(); - } - - /// - /// Asynchronously writes the JSON value delimiter. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - protected override Task WriteValueDelimiterAsync(CancellationToken cancellationToken) - { - return _safeAsync ? DoWriteValueDelimiterAsync(cancellationToken) : base.WriteValueDelimiterAsync(cancellationToken); - } - - internal Task DoWriteValueDelimiterAsync(CancellationToken cancellationToken) - { - return _writer.WriteAsync(',', cancellationToken); - } - - /// - /// Asynchronously writes the specified end token. - /// - /// The end token to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - protected override Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) - { - return _safeAsync ? DoWriteEndAsync(token, cancellationToken) : base.WriteEndAsync(token, cancellationToken); - } - - internal Task DoWriteEndAsync(JsonToken token, CancellationToken cancellationToken) - { - switch (token) - { - case JsonToken.EndObject: - return _writer.WriteAsync('}', cancellationToken); - case JsonToken.EndArray: - return _writer.WriteAsync(']', cancellationToken); - case JsonToken.EndConstructor: - return _writer.WriteAsync(')', cancellationToken); - default: - throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null); - } - } - - /// - /// Asynchronously closes this writer. - /// If is set to true, the destination is also closed. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task CloseAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoCloseAsync(cancellationToken) : base.CloseAsync(cancellationToken); - } - - internal async Task DoCloseAsync(CancellationToken cancellationToken) - { - if (Top == 0) // otherwise will happen in calls to WriteEndAsync - { - cancellationToken.ThrowIfCancellationRequested(); - } - - while (Top > 0) - { - await WriteEndAsync(cancellationToken).ConfigureAwait(false); - } - - CloseBufferAndWriter(); - } - - /// - /// Asynchronously writes the end of the current JSON object or array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteEndAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteEndInternalAsync(cancellationToken) : base.WriteEndAsync(cancellationToken); - } - - /// - /// Asynchronously writes indent characters. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - protected override Task WriteIndentAsync(CancellationToken cancellationToken) - { - return _safeAsync ? DoWriteIndentAsync(cancellationToken) : base.WriteIndentAsync(cancellationToken); - } - - internal Task DoWriteIndentAsync(CancellationToken cancellationToken) - { - // levels of indentation multiplied by the indent count - int currentIndentCount = Top * _indentation; - - int newLineLen = SetIndentChars(); - MiscellaneousUtils.Assert(_indentChars != null); - - if (currentIndentCount <= IndentCharBufferSize) - { - return _writer.WriteAsync(_indentChars, 0, newLineLen + currentIndentCount, cancellationToken); - } - - return WriteIndentAsync(currentIndentCount, newLineLen, cancellationToken); - } - - private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(_indentChars != null); - - await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize), cancellationToken).ConfigureAwait(false); - - while ((currentIndentCount -= IndentCharBufferSize) > 0) - { - await _writer.WriteAsync(_indentChars, newLineLen, Math.Min(currentIndentCount, IndentCharBufferSize), cancellationToken).ConfigureAwait(false); - } - } - - private Task WriteValueInternalAsync(JsonToken token, string value, CancellationToken cancellationToken) - { - Task task = InternalWriteValueAsync(token, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return _writer.WriteAsync(value, cancellationToken); - } - - return WriteValueInternalAsync(task, value, cancellationToken); - } - - private async Task WriteValueInternalAsync(Task task, string value, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await _writer.WriteAsync(value, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes an indent space. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - protected override Task WriteIndentSpaceAsync(CancellationToken cancellationToken) - { - return _safeAsync ? DoWriteIndentSpaceAsync(cancellationToken) : base.WriteIndentSpaceAsync(cancellationToken); - } - - internal Task DoWriteIndentSpaceAsync(CancellationToken cancellationToken) - { - return _writer.WriteAsync(' ', cancellationToken); - } - - /// - /// Asynchronously writes raw JSON without changing the writer's state. - /// - /// The raw JSON to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteRawAsync(json, cancellationToken) : base.WriteRawAsync(json, cancellationToken); - } - - internal Task DoWriteRawAsync(string? json, CancellationToken cancellationToken) - { - return _writer.WriteAsync(json, cancellationToken); - } - - /// - /// Asynchronously writes a null value. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteNullAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteNullAsync(cancellationToken) : base.WriteNullAsync(cancellationToken); - } - - internal Task DoWriteNullAsync(CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Null, JsonConvert.Null, cancellationToken); - } - - private Task WriteDigitsAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) - { - if (uvalue <= 9 & !negative) - { - return _writer.WriteAsync((char)('0' + uvalue), cancellationToken); - } - - int length = WriteNumberToBuffer(uvalue, negative); - return _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken); - } - - private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) - { - Task task = InternalWriteValueAsync(JsonToken.Integer, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return WriteDigitsAsync(uvalue, negative, cancellationToken); - } - - return WriteIntegerValueAsync(task, uvalue, negative, cancellationToken); - } - - private async Task WriteIntegerValueAsync(Task task, ulong uvalue, bool negative, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await WriteDigitsAsync(uvalue, negative, cancellationToken).ConfigureAwait(false); - } - - internal Task WriteIntegerValueAsync(long value, CancellationToken cancellationToken) - { - bool negative = value < 0; - if (negative) - { - value = -value; - } - - return WriteIntegerValueAsync((ulong)value, negative, cancellationToken); - } - - internal Task WriteIntegerValueAsync(ulong uvalue, CancellationToken cancellationToken) - { - return WriteIntegerValueAsync(uvalue, false, cancellationToken); - } - - private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken) - { - return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, this, _writeBuffer!, cancellationToken); - } - - /// - /// Asynchronously writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWritePropertyNameAsync(name, cancellationToken) : base.WritePropertyNameAsync(name, cancellationToken); - } - - internal Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) - { - Task task = InternalWritePropertyNameAsync(name, cancellationToken); - if (!task.IsCompletedSucessfully()) - { - return DoWritePropertyNameAsync(task, name, cancellationToken); - } - - task = WriteEscapedStringAsync(name, QuoteName, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return _writer.WriteAsync(':', cancellationToken); - } - - return JavaScriptUtils.WriteCharAsync(task, _writer, ':', cancellationToken); - } - - private async Task DoWritePropertyNameAsync(Task task, string name, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - - await WriteEscapedStringAsync(name, QuoteName, cancellationToken).ConfigureAwait(false); - - await _writer.WriteAsync(':').ConfigureAwait(false); - } - - /// - /// Asynchronously writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - /// A flag to indicate whether the text should be escaped when it is written as a JSON property name. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWritePropertyNameAsync(name, escape, cancellationToken) : base.WritePropertyNameAsync(name, escape, cancellationToken); - } - - internal async Task DoWritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken) - { - await InternalWritePropertyNameAsync(name, cancellationToken).ConfigureAwait(false); - - if (escape) - { - await WriteEscapedStringAsync(name, QuoteName, cancellationToken).ConfigureAwait(false); - } - else - { - if (QuoteName) - { - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - - await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(false); - - if (QuoteName) - { - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - } - - await _writer.WriteAsync(':').ConfigureAwait(false); - } - - /// - /// Asynchronously writes the beginning of a JSON array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteStartArrayAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteStartArrayAsync(cancellationToken) : base.WriteStartArrayAsync(cancellationToken); - } - - internal Task DoWriteStartArrayAsync(CancellationToken cancellationToken) - { - Task task = InternalWriteStartAsync(JsonToken.StartArray, JsonContainerType.Array, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return _writer.WriteAsync('[', cancellationToken); - } - - return DoWriteStartArrayAsync(task, cancellationToken); - } - - internal async Task DoWriteStartArrayAsync(Task task, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - - await _writer.WriteAsync('[', cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes the beginning of a JSON object. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteStartObjectAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteStartObjectAsync(cancellationToken) : base.WriteStartObjectAsync(cancellationToken); - } - - internal Task DoWriteStartObjectAsync(CancellationToken cancellationToken) - { - Task task = InternalWriteStartAsync(JsonToken.StartObject, JsonContainerType.Object, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return _writer.WriteAsync('{', cancellationToken); - } - - return DoWriteStartObjectAsync(task, cancellationToken); - } - - internal async Task DoWriteStartObjectAsync(Task task, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - - await _writer.WriteAsync('{', cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes the start of a constructor with the given name. - /// - /// The name of the constructor. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteStartConstructorAsync(name, cancellationToken) : base.WriteStartConstructorAsync(name, cancellationToken); - } - - internal async Task DoWriteStartConstructorAsync(string name, CancellationToken cancellationToken) - { - await InternalWriteStartAsync(JsonToken.StartConstructor, JsonContainerType.Constructor, cancellationToken).ConfigureAwait(false); - - await _writer.WriteAsync("new ", cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync('(').ConfigureAwait(false); - } - - /// - /// Asynchronously writes an undefined value. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteUndefinedAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteUndefinedAsync(cancellationToken) : base.WriteUndefinedAsync(cancellationToken); - } - - internal Task DoWriteUndefinedAsync(CancellationToken cancellationToken) - { - Task task = InternalWriteValueAsync(JsonToken.Undefined, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return _writer.WriteAsync(JsonConvert.Undefined, cancellationToken); - } - - return DoWriteUndefinedAsync(task, cancellationToken); - } - - private async Task DoWriteUndefinedAsync(Task task, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await _writer.WriteAsync(JsonConvert.Undefined, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes the given white space. - /// - /// The string of white space characters. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteWhitespaceAsync(ws, cancellationToken) : base.WriteWhitespaceAsync(ws, cancellationToken); - } - - internal Task DoWriteWhitespaceAsync(string ws, CancellationToken cancellationToken) - { - InternalWriteWhitespace(ws); - return _writer.WriteAsync(ws, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(bool value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(bool value, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Boolean, JsonConvert.ToString(value), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(bool? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(byte value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(byte? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a [] value. - /// - /// The [] value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNonNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); - } - - internal async Task WriteValueNonNullAsync(byte[] value, CancellationToken cancellationToken) - { - await InternalWriteValueAsync(JsonToken.Bytes, cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - await Base64Encoder.EncodeAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(false); - await Base64Encoder.FlushAsync(cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(char value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(char value, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.String, JsonConvert.ToString(value), cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(char? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(char? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal async Task DoWriteValueAsync(DateTime value, CancellationToken cancellationToken) - { - await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false); - value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); - - if (StringUtils.IsNullOrEmpty(DateFormatString)) - { - int length = WriteValueToBuffer(value); - - await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); - } - else - { - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - await _writer.WriteAsync(value.ToString(DateFormatString, Culture), cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(DateTime? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal async Task DoWriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken) - { - await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false); - - if (StringUtils.IsNullOrEmpty(DateFormatString)) - { - int length = WriteValueToBuffer(value); - - await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); - } - else - { - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - await _writer.WriteAsync(value.ToString(DateFormatString, Culture), cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(decimal value, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value), cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(decimal? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(double value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteValueAsync(value, false, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task WriteValueAsync(double value, bool nullable, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, nullable), cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(double? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? (value.HasValue ? WriteValueAsync(value.GetValueOrDefault(), true, cancellationToken) : WriteNullAsync(cancellationToken)) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(float value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteValueAsync(value, false, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task WriteValueAsync(float value, bool nullable, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, nullable), cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(float? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? (value.HasValue ? WriteValueAsync(value.GetValueOrDefault(), true, cancellationToken) : WriteNullAsync(cancellationToken)) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal async Task DoWriteValueAsync(Guid value, CancellationToken cancellationToken) - { - await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(false); - - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - await _writer.WriteAsync(value.ToString("D", CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false); -#else - await _writer.WriteAsync(value.ToString("D"), cancellationToken).ConfigureAwait(false); -#endif - await _writer.WriteAsync(_quoteChar).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(Guid? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(int value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(int? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(int? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(long value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(long? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(long? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - -#if HAVE_BIG_INTEGER - internal Task WriteValueAsync(BigInteger value, CancellationToken cancellationToken) - { - return WriteValueInternalAsync(JsonToken.Integer, value.ToString(CultureInfo.InvariantCulture), cancellationToken); - } -#endif - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) - { - if (_safeAsync) - { - if (value == null) - { - return WriteNullAsync(cancellationToken); - } -#if HAVE_BIG_INTEGER - if (value is BigInteger i) - { - return WriteValueAsync(i, cancellationToken); - } -#endif - - return WriteValueAsync(this, ConvertUtils.GetTypeCode(value.GetType()), value, cancellationToken); - } - - return base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(sbyte? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(short value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(short? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(short? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) - { - Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken); - } - - return DoWriteValueAsync(task, value, cancellationToken); - } - - private async Task DoWriteValueAsync(Task task, string? value, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await (value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken)).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal async Task DoWriteValueAsync(TimeSpan value, CancellationToken cancellationToken) - { - await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(value.ToString(null, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(TimeSpan? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(uint value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(uint? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(ulong? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNotNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task WriteValueNotNullAsync(Uri value, CancellationToken cancellationToken) - { - Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return WriteEscapedStringAsync(value.OriginalString, true, cancellationToken); - } - - return WriteValueNotNullAsync(task, value, cancellationToken); - } - - internal async Task WriteValueNotNullAsync(Task task, Uri value, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await WriteEscapedStringAsync(value.OriginalString, true, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default) - { - return _safeAsync ? WriteIntegerValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - - public override Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); - } - - internal Task DoWriteValueAsync(ushort? value, CancellationToken cancellationToken) - { - return value == null ? DoWriteNullAsync(cancellationToken) : WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); - } - - /// - /// Asynchronously writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteCommentAsync(text, cancellationToken) : base.WriteCommentAsync(text, cancellationToken); - } - - internal async Task DoWriteCommentAsync(string? text, CancellationToken cancellationToken) - { - await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(text ?? string.Empty, cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes the end of an array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteEndArrayAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? InternalWriteEndAsync(JsonContainerType.Array, cancellationToken) : base.WriteEndArrayAsync(cancellationToken); - } - - /// - /// Asynchronously writes the end of a constructor. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteEndConstructorAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken) : base.WriteEndConstructorAsync(cancellationToken); - } - - /// - /// Asynchronously writes the end of a JSON object. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteEndObjectAsync(CancellationToken cancellationToken = default) - { - return _safeAsync ? InternalWriteEndAsync(JsonContainerType.Object, cancellationToken) : base.WriteEndObjectAsync(cancellationToken); - } - - /// - /// Asynchronously writes raw JSON where a value is expected and updates the writer's state. - /// - /// The raw JSON to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will - /// execute synchronously, returning an already-completed task. - public override Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) - { - return _safeAsync ? DoWriteRawValueAsync(json, cancellationToken) : base.WriteRawValueAsync(json, cancellationToken); - } - - internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationToken) - { - UpdateScopeWithFinishedValue(); - Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return WriteRawAsync(json, cancellationToken); - } - - return DoWriteRawValueAsync(task, json, cancellationToken); - } - - private async Task DoWriteRawValueAsync(Task task, string? json, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await WriteRawAsync(json, cancellationToken).ConfigureAwait(false); - } - - internal char[] EnsureWriteBuffer(int length, int copyTo) - { - if (length < 35) - { - length = 35; - } - - char[]? buffer = _writeBuffer; - if (buffer == null) - { - return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length); - } - - if (buffer.Length >= length) - { - return buffer; - } - - char[] newBuffer = BufferUtils.RentBuffer(_arrayPool, length); - if (copyTo != 0) - { - Array.Copy(buffer, newBuffer, copyTo); - } - - BufferUtils.ReturnBuffer(_arrayPool, buffer); - _writeBuffer = newBuffer; - return newBuffer; - } - } -} -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.cs deleted file mode 100644 index efb165317..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextWriter.cs +++ /dev/null @@ -1,860 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. - /// - internal partial class JsonTextWriter : JsonWriter - { - private const int IndentCharBufferSize = 12; - private readonly TextWriter _writer; - private Base64Encoder? _base64Encoder; - private char _indentChar; - private int _indentation; - private char _quoteChar; - private bool[]? _charEscapeFlags; - private char[]? _writeBuffer; - private IArrayPool? _arrayPool; - private char[]? _indentChars; - - private Base64Encoder Base64Encoder - { - get - { - if (_base64Encoder == null) _base64Encoder = new Base64Encoder(_writer); - - return _base64Encoder; - } - } - - /// - /// Gets or sets the writer's character array pool. - /// - public IArrayPool? ArrayPool - { - get => _arrayPool; - set - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - _arrayPool = value; - } - } - - /// - /// Gets or sets how many s to write for each level in the hierarchy when - /// is set to . - /// - public int Indentation - { - get => _indentation; - set - { - if (value < 0) throw new ArgumentException("Indentation value must be greater than 0."); - - _indentation = value; - } - } - - /// - /// Gets or sets which character to use to quote attribute values. - /// - public char QuoteChar - { - get => _quoteChar; - set - { - if (value != '"' && value != '\'') - throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and ""."); - - _quoteChar = value; - UpdateCharEscapeFlags(); - } - } - - /// - /// Gets or sets which character to use for indenting when is set to - /// . - /// - public char IndentChar - { - get => _indentChar; - set - { - if (value != _indentChar) - { - _indentChar = value; - _indentChars = null; - } - } - } - - /// - /// Gets or sets a value indicating whether object names will be surrounded with quotes. - /// - public bool QuoteName { get; set; } - - /// - /// Initializes a new instance of the class using the specified . - /// - /// The to write to. - public JsonTextWriter(TextWriter textWriter) - { - if (textWriter == null) throw new ArgumentNullException(nameof(textWriter)); - - _writer = textWriter; - _quoteChar = '"'; - QuoteName = true; - _indentChar = ' '; - _indentation = 2; - - UpdateCharEscapeFlags(); - -#if HAVE_ASYNC - _safeAsync = GetType() == typeof(JsonTextWriter); -#endif - } - - /// - /// Flushes whatever is in the buffer to the underlying and also flushes the underlying - /// . - /// - public override void Flush() => _writer.Flush(); - - /// - /// Closes this writer. - /// If is set to true, the underlying is also - /// closed. - /// If is set to true, the JSON is auto-completed. - /// - public override void Close() - { - base.Close(); - - CloseBufferAndWriter(); - } - - private void CloseBufferAndWriter() - { - if (_writeBuffer != null) - { - BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); - _writeBuffer = null; - } - - if (CloseOutput) - { -#if HAVE_STREAM_READER_WRITER_CLOSE - _writer?.Close(); -#else - _writer?.Dispose(); -#endif - } - } - - /// - /// Writes the beginning of a JSON object. - /// - public override void WriteStartObject() - { - InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); - - _writer.Write('{'); - } - - /// - /// Writes the beginning of a JSON array. - /// - public override void WriteStartArray() - { - InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); - - _writer.Write('['); - } - - /// - /// Writes the start of a constructor with the given name. - /// - /// The name of the constructor. - public override void WriteStartConstructor(string name) - { - InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); - - _writer.Write("new "); - _writer.Write(name); - _writer.Write('('); - } - - /// - /// Writes the specified end token. - /// - /// The end token to write. - protected override void WriteEnd(JsonToken token) - { - switch (token) - { - case JsonToken.EndObject: - _writer.Write('}'); - break; - case JsonToken.EndArray: - _writer.Write(']'); - break; - case JsonToken.EndConstructor: - _writer.Write(')'); - break; - default: - throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null); - } - } - - /// - /// Writes the property name of a name/value pair on a JSON object. - /// - /// The name of the property. - public override void WritePropertyName(string name) - { - InternalWritePropertyName(name); - - WriteEscapedString(name, QuoteName); - - _writer.Write(':'); - } - - /// - /// Writes the property name of a name/value pair on a JSON object. - /// - /// The name of the property. - /// A flag to indicate whether the text should be escaped when it is written as a JSON property name. - public override void WritePropertyName(string name, bool escape) - { - InternalWritePropertyName(name); - - if (escape) - WriteEscapedString(name, QuoteName); - else - { - if (QuoteName) _writer.Write(_quoteChar); - - _writer.Write(name); - - if (QuoteName) _writer.Write(_quoteChar); - } - - _writer.Write(':'); - } - - internal override void OnStringEscapeHandlingChanged() => UpdateCharEscapeFlags(); - - private void UpdateCharEscapeFlags() => _charEscapeFlags = JavaScriptUtils.GetCharEscapeFlags(StringEscapeHandling, _quoteChar); - - /// - /// Writes indent characters. - /// - protected override void WriteIndent() - { - // levels of indentation multiplied by the indent count - var currentIndentCount = Top * _indentation; - - var newLineLen = SetIndentChars(); - - _writer.Write(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize)); - - while ((currentIndentCount -= IndentCharBufferSize) > 0) - _writer.Write(_indentChars, newLineLen, Math.Min(currentIndentCount, IndentCharBufferSize)); - } - - private int SetIndentChars() - { - // Set _indentChars to be a newline followed by IndentCharBufferSize indent characters. - var writerNewLine = _writer.NewLine; - var newLineLen = writerNewLine.Length; - var match = _indentChars != null && _indentChars.Length == IndentCharBufferSize + newLineLen; - if (match) - { - for (var i = 0; i != newLineLen; ++i) - { - if (writerNewLine[i] != _indentChars![i]) - { - match = false; - break; - } - } - } - - if (!match) - { - // If we're here, either _indentChars hasn't been set yet, or _writer.NewLine - // has been changed, or _indentChar has been changed. - _indentChars = (writerNewLine + new string(_indentChar, IndentCharBufferSize)).ToCharArray(); - } - - return newLineLen; - } - - /// - /// Writes the JSON value delimiter. - /// - protected override void WriteValueDelimiter() => _writer.Write(','); - - /// - /// Writes an indent space. - /// - protected override void WriteIndentSpace() => _writer.Write(' '); - - private void WriteValueInternal(string value, JsonToken token) => _writer.Write(value); - - #region WriteValue methods - - /// - /// Writes a value. - /// An error will raised if the value cannot be written as a single JSON token. - /// - /// The value to write. - public override void WriteValue(object? value) - { -#if HAVE_BIG_INTEGER - if (value is BigInteger i) - { - InternalWriteValue(JsonToken.Integer); - WriteValueInternal(i.ToString(CultureInfo.InvariantCulture), JsonToken.String); - } - else -#endif - { - base.WriteValue(value); - } - } - - /// - /// Writes a null value. - /// - public override void WriteNull() - { - InternalWriteValue(JsonToken.Null); - WriteValueInternal(JsonConvert.Null, JsonToken.Null); - } - - /// - /// Writes an undefined value. - /// - public override void WriteUndefined() - { - InternalWriteValue(JsonToken.Undefined); - WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined); - } - - /// - /// Writes raw JSON. - /// - /// The raw JSON to write. - public override void WriteRaw(string? json) - { - InternalWriteRaw(); - - _writer.Write(json); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(string? value) - { - InternalWriteValue(JsonToken.String); - - if (value == null) - WriteValueInternal(JsonConvert.Null, JsonToken.Null); - else - WriteEscapedString(value, true); - } - - private void WriteEscapedString(string value, bool quote) - { - EnsureWriteBuffer(); - JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, _arrayPool, - ref _writeBuffer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(int value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(uint value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(long value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ulong value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value, false); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(float value) - { - InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public override void WriteValue(float? value) - { - if (value == null) - WriteNull(); - else - { - InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), FloatFormatHandling, QuoteChar, true), JsonToken.Float); - } - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(double value) - { - InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public override void WriteValue(double? value) - { - if (value == null) - WriteNull(); - else - { - InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), FloatFormatHandling, QuoteChar, true), JsonToken.Float); - } - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(bool value) - { - InternalWriteValue(JsonToken.Boolean); - WriteValueInternal(JsonConvert.ToString(value), JsonToken.Boolean); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(short value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ushort value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(char value) - { - InternalWriteValue(JsonToken.String); - WriteValueInternal(JsonConvert.ToString(value), JsonToken.String); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(byte value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(sbyte value) - { - InternalWriteValue(JsonToken.Integer); - WriteIntegerValue(value); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(decimal value) - { - InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value), JsonToken.Float); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTime value) - { - InternalWriteValue(JsonToken.Date); - value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); - - if (StringUtils.IsNullOrEmpty(DateFormatString)) - { - var length = WriteValueToBuffer(value); - - _writer.Write(_writeBuffer, 0, length); - } - else - { - _writer.Write(_quoteChar); - _writer.Write(value.ToString(DateFormatString, Culture)); - _writer.Write(_quoteChar); - } - } - - private int WriteValueToBuffer(DateTime value) - { - EnsureWriteBuffer(); - MiscellaneousUtils.Assert(_writeBuffer != null); - - var pos = 0; - _writeBuffer[pos++] = _quoteChar; - pos = DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, value, null, value.Kind, DateFormatHandling); - _writeBuffer[pos++] = _quoteChar; - return pos; - } - - /// - /// Writes a [] value. - /// - /// The [] value to write. - public override void WriteValue(byte[]? value) - { - if (value == null) - WriteNull(); - else - { - InternalWriteValue(JsonToken.Bytes); - _writer.Write(_quoteChar); - Base64Encoder.Encode(value, 0, value.Length); - Base64Encoder.Flush(); - _writer.Write(_quoteChar); - } - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTimeOffset value) - { - InternalWriteValue(JsonToken.Date); - - if (StringUtils.IsNullOrEmpty(DateFormatString)) - { - int length = WriteValueToBuffer(value); - - _writer.Write(_writeBuffer, 0, length); - } - else - { - _writer.Write(_quoteChar); - _writer.Write(value.ToString(DateFormatString, Culture)); - _writer.Write(_quoteChar); - } - } - - private int WriteValueToBuffer(DateTimeOffset value) - { - EnsureWriteBuffer(); - MiscellaneousUtils.Assert(_writeBuffer != null); - - int pos = 0; - _writeBuffer[pos++] = _quoteChar; - pos = - DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, (DateFormatHandling == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, DateFormatHandling); - _writeBuffer[pos++] = _quoteChar; - return pos; - } -#endif - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Guid value) - { - InternalWriteValue(JsonToken.String); - - string text; - -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - text = value.ToString("D", CultureInfo.InvariantCulture); -#else - text = value.ToString("D"); -#endif - - _writer.Write(_quoteChar); - _writer.Write(text); - _writer.Write(_quoteChar); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(TimeSpan value) - { - InternalWriteValue(JsonToken.String); - - string text; -#if !HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE - text = value.ToString(); -#else - text = value.ToString(null, CultureInfo.InvariantCulture); -#endif - - _writer.Write(_quoteChar); - _writer.Write(text); - _writer.Write(_quoteChar); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Uri? value) - { - if (value == null) - WriteNull(); - else - { - InternalWriteValue(JsonToken.String); - WriteEscapedString(value.OriginalString, true); - } - } - - #endregion - - /// - /// Writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - public override void WriteComment(string? text) - { - InternalWriteComment(); - - _writer.Write("/*"); - _writer.Write(text); - _writer.Write("*/"); - } - - /// - /// Writes the given white space. - /// - /// The string of white space characters. - public override void WriteWhitespace(string ws) - { - InternalWriteWhitespace(ws); - - _writer.Write(ws); - } - - private void EnsureWriteBuffer() - { - if (_writeBuffer == null) - { - // maximum buffer sized used when writing iso date - _writeBuffer = BufferUtils.RentBuffer(_arrayPool, 35); - } - } - - private void WriteIntegerValue(long value) - { - if (value >= 0 && value <= 9) - _writer.Write((char)('0' + value)); - else - { - var negative = value < 0; - WriteIntegerValue(negative ? (ulong)-value : (ulong)value, negative); - } - } - - private void WriteIntegerValue(ulong value, bool negative) - { - if (!negative & (value <= 9)) - _writer.Write((char)('0' + value)); - else - { - var length = WriteNumberToBuffer(value, negative); - _writer.Write(_writeBuffer, 0, length); - } - } - - private int WriteNumberToBuffer(ulong value, bool negative) - { - if (value <= uint.MaxValue) - { - // avoid the 64 bit division if possible - return WriteNumberToBuffer((uint)value, negative); - } - - EnsureWriteBuffer(); - MiscellaneousUtils.Assert(_writeBuffer != null); - - var totalLength = MathUtils.IntLength(value); - - if (negative) - { - totalLength++; - _writeBuffer[0] = '-'; - } - - var index = totalLength; - - do - { - var quotient = value / 10; - var digit = value - quotient * 10; - _writeBuffer[--index] = (char)('0' + digit); - value = quotient; - } while (value != 0); - - return totalLength; - } - - private void WriteIntegerValue(int value) - { - if (value >= 0 && value <= 9) - _writer.Write((char)('0' + value)); - else - { - var negative = value < 0; - WriteIntegerValue(negative ? (uint)-value : (uint)value, negative); - } - } - - private void WriteIntegerValue(uint value, bool negative) - { - if (!negative & (value <= 9)) - _writer.Write((char)('0' + value)); - else - { - var length = WriteNumberToBuffer(value, negative); - _writer.Write(_writeBuffer, 0, length); - } - } - - private int WriteNumberToBuffer(uint value, bool negative) - { - EnsureWriteBuffer(); - MiscellaneousUtils.Assert(_writeBuffer != null); - - var totalLength = MathUtils.IntLength(value); - - if (negative) - { - totalLength++; - _writeBuffer[0] = '-'; - } - - var index = totalLength; - - do - { - var quotient = value / 10; - var digit = value - quotient * 10; - _writeBuffer[--index] = (char)('0' + digit); - value = quotient; - } while (value != 0); - - return totalLength; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonToken.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonToken.cs deleted file mode 100644 index 78c6dff15..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonToken.cs +++ /dev/null @@ -1,126 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies the type of JSON token. - /// - internal enum JsonToken - { - /// - /// This is returned by the if a read method has not been called. - /// - None = 0, - - /// - /// An object start token. - /// - StartObject = 1, - - /// - /// An array start token. - /// - StartArray = 2, - - /// - /// A constructor start token. - /// - StartConstructor = 3, - - /// - /// An object property name. - /// - PropertyName = 4, - - /// - /// A comment. - /// - Comment = 5, - - /// - /// Raw JSON. - /// - Raw = 6, - - /// - /// An integer. - /// - Integer = 7, - - /// - /// A float. - /// - Float = 8, - - /// - /// A string. - /// - String = 9, - - /// - /// A boolean. - /// - Boolean = 10, - - /// - /// A null token. - /// - Null = 11, - - /// - /// An undefined token. - /// - Undefined = 12, - - /// - /// An object end token. - /// - EndObject = 13, - - /// - /// An array end token. - /// - EndArray = 14, - - /// - /// A constructor end token. - /// - EndConstructor = 15, - - /// - /// A Date. - /// - Date = 16, - - /// - /// Byte data. - /// - Bytes = 17 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonValidatingReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonValidatingReader.cs deleted file mode 100644 index e1dbbf7a9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonValidatingReader.cs +++ /dev/null @@ -1,895 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text.RegularExpressions; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Schema; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// - /// Represents a reader that provides validation. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonValidatingReader : JsonReader, IJsonLineInfo - { - private class SchemaScope - { - public SchemaScope(JTokenType tokenType, IList schemas) - { - TokenType = tokenType; - Schemas = schemas; - - RequiredProperties = schemas.SelectMany(GetRequiredProperties).Distinct().ToDictionary(p => p, p => false); - - if (tokenType == JTokenType.Array && schemas.Any(s => s.UniqueItems)) - { - IsUniqueArray = true; - UniqueArrayItems = new List(); - } - } - - public int ArrayItemCount { get; set; } - public JTokenWriter CurrentItemWriter { get; set; } - - public string CurrentPropertyName { get; set; } - public bool IsUniqueArray { get; } - - public Dictionary RequiredProperties { get; } - - public IList Schemas { get; } - - public JTokenType TokenType { get; } - - public IList UniqueArrayItems { get; } - - private IEnumerable GetRequiredProperties(JsonSchemaModel schema) - { - if (schema?.Properties == null) return Enumerable.Empty(); - - return schema.Properties.Where(p => p.Value.Required).Select(p => p.Key); - } - } - - private readonly Stack _stack; - private JsonSchema _schema; - private JsonSchemaModel _model; - private SchemaScope _currentScope; - - /// - /// Sets an event handler for receiving schema validation errors. - /// - public event ValidationEventHandler ValidationEventHandler; - - /// - /// Gets the text value of the current JSON token. - /// - /// - public override object Value => Reader.Value; - - /// - /// Gets the depth of the current token in the JSON document. - /// - /// The depth of the current token in the JSON document. - public override int Depth => Reader.Depth; - - /// - /// Gets the path of the current JSON token. - /// - public override string Path => Reader.Path; - - /// - /// Gets the quotation mark character used to enclose the value of a string. - /// - /// - public override char QuoteChar - { - get => Reader.QuoteChar; - protected internal set { } - } - - /// - /// Gets the type of the current JSON token. - /// - /// - public override JsonToken TokenType => Reader.TokenType; - - /// - /// Gets the .NET type for the current JSON token. - /// - /// - public override Type ValueType => Reader.ValueType; - - private void Push(SchemaScope scope) - { - _stack.Push(scope); - _currentScope = scope; - } - - private SchemaScope Pop() - { - var poppedScope = _stack.Pop(); - _currentScope = _stack.Count != 0 - ? _stack.Peek() - : null; - - return poppedScope; - } - - private IList CurrentSchemas => _currentScope.Schemas; - - private static readonly IList EmptySchemaList = new List(); - - private IList CurrentMemberSchemas - { - get - { - if (_currentScope == null) return new List(new[] { _model }); - - if (_currentScope.Schemas == null || _currentScope.Schemas.Count == 0) return EmptySchemaList; - - switch (_currentScope.TokenType) - { - case JTokenType.None: - return _currentScope.Schemas; - case JTokenType.Object: - { - if (_currentScope.CurrentPropertyName == null) - throw new JsonReaderException("CurrentPropertyName has not been set on scope."); - - IList schemas = new List(); - - foreach (var schema in CurrentSchemas) - { - if (schema.Properties != null && schema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out var propertySchema)) - schemas.Add(propertySchema); - if (schema.PatternProperties != null) - { - foreach (var patternProperty in schema.PatternProperties) - { - if (Regex.IsMatch(_currentScope.CurrentPropertyName, patternProperty.Key)) schemas.Add(patternProperty.Value); - } - } - - if (schemas.Count == 0 && schema.AllowAdditionalProperties && schema.AdditionalProperties != null) - schemas.Add(schema.AdditionalProperties); - } - - return schemas; - } - case JTokenType.Array: - { - IList schemas = new List(); - - foreach (var schema in CurrentSchemas) - { - if (!schema.PositionalItemsValidation) - { - if (schema.Items != null && schema.Items.Count > 0) schemas.Add(schema.Items[0]); - } - else - { - if (schema.Items != null && schema.Items.Count > 0) - { - if (schema.Items.Count > _currentScope.ArrayItemCount - 1) - schemas.Add(schema.Items[_currentScope.ArrayItemCount - 1]); - } - - if (schema.AllowAdditionalItems && schema.AdditionalItems != null) schemas.Add(schema.AdditionalItems); - } - } - - return schemas; - } - case JTokenType.Constructor: - return EmptySchemaList; - default: - throw new ArgumentOutOfRangeException("TokenType", - "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType)); - } - } - } - - private void RaiseError(string message, JsonSchemaModel schema) - { - IJsonLineInfo lineInfo = this; - - var exceptionMessage = lineInfo.HasLineInfo() - ? message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition) - : message; - - OnValidationEvent(new JsonSchemaException(exceptionMessage, null, Path, lineInfo.LineNumber, lineInfo.LinePosition)); - } - - private void OnValidationEvent(JsonSchemaException exception) - { - var handler = ValidationEventHandler; - if (handler != null) - handler(this, new ValidationEventArgs(exception)); - else - throw exception; - } - - /// - /// Initializes a new instance of the class that - /// validates the content returned from the given . - /// - /// The to read from while validating. - public JsonValidatingReader(JsonReader reader) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - Reader = reader; - _stack = new Stack(); - } - - /// - /// Gets or sets the schema. - /// - /// The schema. - public JsonSchema Schema - { - get => _schema; - set - { - if (TokenType != JsonToken.None) throw new InvalidOperationException("Cannot change schema while validating JSON."); - - _schema = value; - _model = null; - } - } - - /// - /// Gets the used to construct this . - /// - /// The specified in the constructor. - public JsonReader Reader { get; } - - /// - /// Changes the reader's state to . - /// If is set to true, the underlying is also closed. - /// - public override void Close() - { - base.Close(); - if (CloseInput) Reader?.Close(); - } - - private void ValidateNotDisallowed(JsonSchemaModel schema) - { - if (schema == null) return; - - var currentNodeType = GetCurrentNodeSchemaType(); - if (currentNodeType != null) - { - if (JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeType.GetValueOrDefault())) - RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeType), schema); - } - } - - private JsonSchemaType? GetCurrentNodeSchemaType() - { - switch (Reader.TokenType) - { - case JsonToken.StartObject: - return JsonSchemaType.Object; - case JsonToken.StartArray: - return JsonSchemaType.Array; - case JsonToken.Integer: - return JsonSchemaType.Integer; - case JsonToken.Float: - return JsonSchemaType.Float; - case JsonToken.String: - return JsonSchemaType.String; - case JsonToken.Boolean: - return JsonSchemaType.Boolean; - case JsonToken.Null: - return JsonSchemaType.Null; - default: - return null; - } - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// A of . - public override int? ReadAsInt32() - { - var i = Reader.ReadAsInt32(); - - ValidateCurrentToken(); - return i; - } - - /// - /// Reads the next JSON token from the underlying as a []. - /// - /// - /// A [] or null if the next JSON token is null. - /// - public override byte[] ReadAsBytes() - { - var data = Reader.ReadAsBytes(); - - ValidateCurrentToken(); - return data; - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// A of . - public override decimal? ReadAsDecimal() - { - var d = Reader.ReadAsDecimal(); - - ValidateCurrentToken(); - return d; - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// A of . - public override double? ReadAsDouble() - { - var d = Reader.ReadAsDouble(); - - ValidateCurrentToken(); - return d; - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// A of . - public override bool? ReadAsBoolean() - { - var b = Reader.ReadAsBoolean(); - - ValidateCurrentToken(); - return b; - } - - /// - /// Reads the next JSON token from the underlying as a . - /// - /// A . This method will return null at the end of an array. - public override string ReadAsString() - { - var s = Reader.ReadAsString(); - - ValidateCurrentToken(); - return s; - } - - /// - /// Reads the next JSON token from the underlying as a of - /// . - /// - /// - /// A of . This method will return null at the end of an - /// array. - /// - public override DateTime? ReadAsDateTime() - { - var dateTime = Reader.ReadAsDateTime(); - - ValidateCurrentToken(); - return dateTime; - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Reads the next JSON token from the underlying as a of . - /// - /// A of . - public override DateTimeOffset? ReadAsDateTimeOffset() - { - DateTimeOffset? dateTimeOffset = Reader.ReadAsDateTimeOffset(); - - ValidateCurrentToken(); - return dateTimeOffset; - } -#endif - - /// - /// Reads the next JSON token from the underlying . - /// - /// - /// true if the next token was read successfully; false if there are no more tokens to read. - /// - public override bool Read() - { - if (!Reader.Read()) return false; - - if (Reader.TokenType == JsonToken.Comment) return true; - - ValidateCurrentToken(); - return true; - } - - private void ValidateCurrentToken() - { - // first time validate has been called. build model - if (_model == null) - { - var builder = new JsonSchemaModelBuilder(); - _model = builder.Build(_schema); - - if (!JsonTokenUtils.IsStartToken(Reader.TokenType)) Push(new SchemaScope(JTokenType.None, CurrentMemberSchemas)); - } - - switch (Reader.TokenType) - { - case JsonToken.StartObject: - ProcessValue(); - IList objectSchemas = CurrentMemberSchemas.Where(ValidateObject).ToList(); - Push(new SchemaScope(JTokenType.Object, objectSchemas)); - WriteToken(CurrentSchemas); - break; - case JsonToken.StartArray: - ProcessValue(); - IList arraySchemas = CurrentMemberSchemas.Where(ValidateArray).ToList(); - Push(new SchemaScope(JTokenType.Array, arraySchemas)); - WriteToken(CurrentSchemas); - break; - case JsonToken.StartConstructor: - ProcessValue(); - Push(new SchemaScope(JTokenType.Constructor, null)); - WriteToken(CurrentSchemas); - break; - case JsonToken.PropertyName: - WriteToken(CurrentSchemas); - foreach (var schema in CurrentSchemas) ValidatePropertyName(schema); - break; - case JsonToken.Raw: - ProcessValue(); - break; - case JsonToken.Integer: - ProcessValue(); - WriteToken(CurrentMemberSchemas); - foreach (var schema in CurrentMemberSchemas) ValidateInteger(schema); - break; - case JsonToken.Float: - ProcessValue(); - WriteToken(CurrentMemberSchemas); - foreach (var schema in CurrentMemberSchemas) ValidateFloat(schema); - break; - case JsonToken.String: - ProcessValue(); - WriteToken(CurrentMemberSchemas); - foreach (var schema in CurrentMemberSchemas) ValidateString(schema); - break; - case JsonToken.Boolean: - ProcessValue(); - WriteToken(CurrentMemberSchemas); - foreach (var schema in CurrentMemberSchemas) ValidateBoolean(schema); - break; - case JsonToken.Null: - ProcessValue(); - WriteToken(CurrentMemberSchemas); - foreach (var schema in CurrentMemberSchemas) ValidateNull(schema); - break; - case JsonToken.EndObject: - WriteToken(CurrentSchemas); - foreach (var schema in CurrentSchemas) ValidateEndObject(schema); - Pop(); - break; - case JsonToken.EndArray: - WriteToken(CurrentSchemas); - foreach (var schema in CurrentSchemas) ValidateEndArray(schema); - Pop(); - break; - case JsonToken.EndConstructor: - WriteToken(CurrentSchemas); - Pop(); - break; - case JsonToken.Undefined: - case JsonToken.Date: - case JsonToken.Bytes: - // these have no equivalent in JSON schema - WriteToken(CurrentMemberSchemas); - break; - case JsonToken.None: - // no content, do nothing - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private void WriteToken(IList schemas) - { - foreach (var schemaScope in _stack) - { - var isInUniqueArray = schemaScope.TokenType == JTokenType.Array && schemaScope.IsUniqueArray && schemaScope.ArrayItemCount > 0; - - if (isInUniqueArray || schemas.Any(s => s.Enum != null)) - { - if (schemaScope.CurrentItemWriter == null) - { - if (JsonTokenUtils.IsEndToken(Reader.TokenType)) continue; - - schemaScope.CurrentItemWriter = new JTokenWriter(); - } - - schemaScope.CurrentItemWriter.WriteToken(Reader, false); - - // finished writing current item - if (schemaScope.CurrentItemWriter.Top == 0 && Reader.TokenType != JsonToken.PropertyName) - { - var finishedItem = schemaScope.CurrentItemWriter.Token; - - // start next item with new writer - schemaScope.CurrentItemWriter = null; - - if (isInUniqueArray) - { - if (schemaScope.UniqueArrayItems.Contains(finishedItem, JToken.EqualityComparer)) - RaiseError( - "Non-unique array item at index {0}.".FormatWith(CultureInfo.InvariantCulture, schemaScope.ArrayItemCount - 1), - schemaScope.Schemas.First(s => s.UniqueItems)); - - schemaScope.UniqueArrayItems.Add(finishedItem); - } - else if (schemas.Any(s => s.Enum != null)) - { - foreach (var schema in schemas) - { - if (schema.Enum != null) - { - if (!schema.Enum.ContainsValue(finishedItem, JToken.EqualityComparer)) - { - var sw = new StringWriter(CultureInfo.InvariantCulture); - finishedItem.WriteTo(new JsonTextWriter(sw)); - - RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, sw.ToString()), - schema); - } - } - } - } - } - } - } - } - - private void ValidateEndObject(JsonSchemaModel schema) - { - if (schema == null) return; - - var requiredProperties = _currentScope.RequiredProperties; - - if (requiredProperties != null && requiredProperties.Values.Any(v => !v)) - { - var unmatchedRequiredProperties = requiredProperties.Where(kv => !kv.Value).Select(kv => kv.Key); - RaiseError("Required properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", - unmatchedRequiredProperties -#if !HAVE_STRING_JOIN_WITH_ENUMERABLE - .ToArray() -#endif - )), schema); - } - } - - private void ValidateEndArray(JsonSchemaModel schema) - { - if (schema == null) return; - - var arrayItemCount = _currentScope.ArrayItemCount; - - if (schema.MaximumItems != null && arrayItemCount > schema.MaximumItems) - RaiseError( - "Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, - schema.MaximumItems), schema); - - if (schema.MinimumItems != null && arrayItemCount < schema.MinimumItems) - RaiseError( - "Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, - schema.MinimumItems), schema); - } - - private void ValidateNull(JsonSchemaModel schema) - { - if (schema == null) return; - - if (!TestType(schema, JsonSchemaType.Null)) return; - - ValidateNotDisallowed(schema); - } - - private void ValidateBoolean(JsonSchemaModel schema) - { - if (schema == null) return; - - if (!TestType(schema, JsonSchemaType.Boolean)) return; - - ValidateNotDisallowed(schema); - } - - private void ValidateString(JsonSchemaModel schema) - { - if (schema == null) return; - - if (!TestType(schema, JsonSchemaType.String)) return; - - ValidateNotDisallowed(schema); - - var value = Reader.Value.ToString(); - - if (schema.MaximumLength != null && value.Length > schema.MaximumLength) - RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MaximumLength), - schema); - - if (schema.MinimumLength != null && value.Length < schema.MinimumLength) - RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MinimumLength), - schema); - - if (schema.Patterns != null) - { - foreach (var pattern in schema.Patterns) - { - if (!Regex.IsMatch(value, pattern)) - RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, value, pattern), - schema); - } - } - } - - private void ValidateInteger(JsonSchemaModel schema) - { - if (schema == null) return; - - if (!TestType(schema, JsonSchemaType.Integer)) return; - - ValidateNotDisallowed(schema); - - var value = Reader.Value; - - if (schema.Maximum != null) - { - if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0) - RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); - if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0) - RaiseError( - "Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, - schema.Maximum), schema); - } - - if (schema.Minimum != null) - { - if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0) - RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), - schema); - if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0) - RaiseError( - "Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, - schema.Minimum), schema); - } - - if (schema.DivisibleBy != null) - { - bool notDivisible; -#if HAVE_BIG_INTEGER - if (value is BigInteger i) - { - // not that this will lose any decimal point on DivisibleBy - // so manually raise an error if DivisibleBy is not an integer and value is not zero - bool divisibleNonInteger = !Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0); - if (divisibleNonInteger) - { - notDivisible = i != 0; - } - else - { - notDivisible = i % new BigInteger(schema.DivisibleBy.Value) != 0; - } - } - else -#endif - { - notDivisible = !IsZero(Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.GetValueOrDefault()); - } - - if (notDivisible) - RaiseError( - "Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), - schema.DivisibleBy), schema); - } - } - - private void ProcessValue() - { - if (_currentScope != null && _currentScope.TokenType == JTokenType.Array) - { - _currentScope.ArrayItemCount++; - - foreach (var currentSchema in CurrentSchemas) - { - // if there is positional validation and the array index is past the number of item validation schemas and there are no additional items then error - if (currentSchema != null - && currentSchema.PositionalItemsValidation - && !currentSchema.AllowAdditionalItems - && (currentSchema.Items == null || _currentScope.ArrayItemCount - 1 >= currentSchema.Items.Count)) - RaiseError( - "Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, - _currentScope.ArrayItemCount), currentSchema); - } - } - } - - private void ValidateFloat(JsonSchemaModel schema) - { - if (schema == null) return; - - if (!TestType(schema, JsonSchemaType.Float)) return; - - ValidateNotDisallowed(schema); - - var value = Convert.ToDouble(Reader.Value, CultureInfo.InvariantCulture); - - if (schema.Maximum != null) - { - if (value > schema.Maximum) - RaiseError( - "Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), - schema.Maximum), schema); - if (schema.ExclusiveMaximum && value == schema.Maximum) - RaiseError( - "Float {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, - JsonConvert.ToString(value), schema.Maximum), schema); - } - - if (schema.Minimum != null) - { - if (value < schema.Minimum) - RaiseError( - "Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), - schema.Minimum), schema); - if (schema.ExclusiveMinimum && value == schema.Minimum) - RaiseError( - "Float {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, - JsonConvert.ToString(value), schema.Minimum), schema); - } - - if (schema.DivisibleBy != null) - { - var remainder = FloatingPointRemainder(value, schema.DivisibleBy.GetValueOrDefault()); - - if (!IsZero(remainder)) - RaiseError( - "Float {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), - schema.DivisibleBy), schema); - } - } - - private static double FloatingPointRemainder(double dividend, double divisor) => dividend - Math.Floor(dividend / divisor) * divisor; - - private static bool IsZero(double value) - { - const double epsilon = 2.2204460492503131e-016; - - return Math.Abs(value) < 20.0 * epsilon; - } - - private void ValidatePropertyName(JsonSchemaModel schema) - { - if (schema == null) return; - - var propertyName = Convert.ToString(Reader.Value, CultureInfo.InvariantCulture); - - if (_currentScope.RequiredProperties.ContainsKey(propertyName)) _currentScope.RequiredProperties[propertyName] = true; - - if (!schema.AllowAdditionalProperties) - { - var propertyDefinied = IsPropertyDefinied(schema, propertyName); - - if (!propertyDefinied) - RaiseError( - "Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith( - CultureInfo.InvariantCulture, propertyName), schema); - } - - _currentScope.CurrentPropertyName = propertyName; - } - - private bool IsPropertyDefinied(JsonSchemaModel schema, string propertyName) - { - if (schema.Properties != null && schema.Properties.ContainsKey(propertyName)) return true; - - if (schema.PatternProperties != null) - { - foreach (var pattern in schema.PatternProperties.Keys) - { - if (Regex.IsMatch(propertyName, pattern)) return true; - } - } - - return false; - } - - private bool ValidateArray(JsonSchemaModel schema) - { - if (schema == null) return true; - - return TestType(schema, JsonSchemaType.Array); - } - - private bool ValidateObject(JsonSchemaModel schema) - { - if (schema == null) return true; - - return TestType(schema, JsonSchemaType.Object); - } - - private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType) - { - if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType)) - { - RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), - currentSchema); - return false; - } - - return true; - } - - bool IJsonLineInfo.HasLineInfo() => Reader is IJsonLineInfo lineInfo && lineInfo.HasLineInfo(); - - int IJsonLineInfo.LineNumber => Reader is IJsonLineInfo lineInfo ? lineInfo.LineNumber : 0; - - int IJsonLineInfo.LinePosition => Reader is IJsonLineInfo lineInfo ? lineInfo.LinePosition : 0; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.Async.cs deleted file mode 100644 index bbb902b2a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.Async.cs +++ /dev/null @@ -1,1799 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -using System.Threading; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - internal abstract partial class JsonWriter - { - internal Task AutoCompleteAsync(JsonToken tokenBeingWritten, CancellationToken cancellationToken) - { - State oldState = _currentState; - - // gets new state based on the current state and what is being written - State newState = StateArray[(int)tokenBeingWritten][(int)oldState]; - - if (newState == State.Error) - { - throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), oldState.ToString()), null); - } - - _currentState = newState; - - if (_formatting == Formatting.Indented) - { - switch (oldState) - { - case State.Start: - break; - case State.Property: - return WriteIndentSpaceAsync(cancellationToken); - case State.ArrayStart: - case State.ConstructorStart: - return WriteIndentAsync(cancellationToken); - case State.Array: - case State.Constructor: - return tokenBeingWritten == JsonToken.Comment ? WriteIndentAsync(cancellationToken) : AutoCompleteAsync(cancellationToken); - case State.Object: - switch (tokenBeingWritten) - { - case JsonToken.Comment: - break; - case JsonToken.PropertyName: - return AutoCompleteAsync(cancellationToken); - default: - return WriteValueDelimiterAsync(cancellationToken); - } - - break; - default: - if (tokenBeingWritten == JsonToken.PropertyName) - { - return WriteIndentAsync(cancellationToken); - } - - break; - } - } - else if (tokenBeingWritten != JsonToken.Comment) - { - switch (oldState) - { - case State.Object: - case State.Array: - case State.Constructor: - return WriteValueDelimiterAsync(cancellationToken); - } - } - - return AsyncUtils.CompletedTask; - } - - private async Task AutoCompleteAsync(CancellationToken cancellationToken) - { - await WriteValueDelimiterAsync(cancellationToken).ConfigureAwait(false); - await WriteIndentAsync(cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously closes this writer. - /// If is set to true, the destination is also closed. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task CloseAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - Close(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task FlushAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - Flush(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the specified end token. - /// - /// The end token to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - protected virtual Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteEnd(token); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes indent characters. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - protected virtual Task WriteIndentAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteIndent(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the JSON value delimiter. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - protected virtual Task WriteValueDelimiterAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValueDelimiter(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes an indent space. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - protected virtual Task WriteIndentSpaceAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteIndentSpace(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes raw JSON without changing the writer's state. - /// - /// The raw JSON to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteRaw(json); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the end of the current JSON object or array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteEndAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteEnd(); - return AsyncUtils.CompletedTask; - } - - internal Task WriteEndInternalAsync(CancellationToken cancellationToken) - { - JsonContainerType type = Peek(); - switch (type) - { - case JsonContainerType.Object: - return WriteEndObjectAsync(cancellationToken); - case JsonContainerType.Array: - return WriteEndArrayAsync(cancellationToken); - case JsonContainerType.Constructor: - return WriteEndConstructorAsync(cancellationToken); - default: - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null); - } - } - - internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - int levelsToComplete = CalculateLevelsToComplete(type); - while (levelsToComplete-- > 0) - { - JsonToken token = GetCloseTokenForType(Pop()); - - Task t; - if (_currentState == State.Property) - { - t = WriteNullAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) - { - return AwaitProperty(t, levelsToComplete, token, cancellationToken); - } - } - - if (_formatting == Formatting.Indented) - { - if (_currentState != State.ObjectStart && _currentState != State.ArrayStart) - { - t = WriteIndentAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) - { - return AwaitIndent(t, levelsToComplete, token, cancellationToken); - } - } - } - - t = WriteEndAsync(token, cancellationToken); - if (!t.IsCompletedSucessfully()) - { - return AwaitEnd(t, levelsToComplete, cancellationToken); - } - - UpdateCurrentState(); - } - - return AsyncUtils.CompletedTask; - - // Local functions, params renamed (capitalized) so as not to capture and allocate when calling async - async Task AwaitProperty(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) - { - await task.ConfigureAwait(false); - - // Finish current loop - if (_formatting == Formatting.Indented) - { - if (_currentState != State.ObjectStart && _currentState != State.ArrayStart) - { - await WriteIndentAsync(CancellationToken).ConfigureAwait(false); - } - } - - await WriteEndAsync(token, CancellationToken).ConfigureAwait(false); - - UpdateCurrentState(); - - await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(false); - } - - async Task AwaitIndent(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) - { - await task.ConfigureAwait(false); - - // Finish current loop - - await WriteEndAsync(token, CancellationToken).ConfigureAwait(false); - - UpdateCurrentState(); - - await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(false); - } - - async Task AwaitEnd(Task task, int LevelsToComplete, CancellationToken CancellationToken) - { - await task.ConfigureAwait(false); - - // Finish current loop - - UpdateCurrentState(); - - await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(false); - } - - async Task AwaitRemaining(int LevelsToComplete, CancellationToken CancellationToken) - { - while (LevelsToComplete-- > 0) - { - JsonToken token = GetCloseTokenForType(Pop()); - - if (_currentState == State.Property) - { - await WriteNullAsync(CancellationToken).ConfigureAwait(false); - } - - if (_formatting == Formatting.Indented) - { - if (_currentState != State.ObjectStart && _currentState != State.ArrayStart) - { - await WriteIndentAsync(CancellationToken).ConfigureAwait(false); - } - } - - await WriteEndAsync(token, CancellationToken).ConfigureAwait(false); - - UpdateCurrentState(); - } - } - } - - /// - /// Asynchronously writes the end of an array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteEndArrayAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteEndArray(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the end of a constructor. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteEndConstructorAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteEndConstructor(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the end of a JSON object. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteEndObjectAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteEndObject(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a null value. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteNullAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteNull(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WritePropertyName(name); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - /// A flag to indicate whether the text should be escaped when it is written as a JSON property name. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WritePropertyName(name, escape); - return AsyncUtils.CompletedTask; - } - - internal Task InternalWritePropertyNameAsync(string name, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - _currentPosition.PropertyName = name; - return AutoCompleteAsync(JsonToken.PropertyName, cancellationToken); - } - - /// - /// Asynchronously writes the beginning of a JSON array. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteStartArrayAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteStartArray(); - return AsyncUtils.CompletedTask; - } - - internal async Task InternalWriteStartAsync(JsonToken token, JsonContainerType container, CancellationToken cancellationToken) - { - UpdateScopeWithFinishedValue(); - await AutoCompleteAsync(token, cancellationToken).ConfigureAwait(false); - Push(container); - } - - /// - /// Asynchronously writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteComment(text); - return AsyncUtils.CompletedTask; - } - - internal Task InternalWriteCommentAsync(CancellationToken cancellationToken) - { - return AutoCompleteAsync(JsonToken.Comment, cancellationToken); - } - - /// - /// Asynchronously writes raw JSON where a value is expected and updates the writer's state. - /// - /// The raw JSON to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteRawValue(json); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the start of a constructor with the given name. - /// - /// The name of the constructor. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteStartConstructor(name); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the beginning of a JSON object. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteStartObjectAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteStartObject(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the current token. - /// - /// The to read the token from. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public Task WriteTokenAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return WriteTokenAsync(reader, true, cancellationToken); - } - - /// - /// Asynchronously writes the current token. - /// - /// The to read the token from. - /// A flag indicating whether the current token's children should be written. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public Task WriteTokenAsync(JsonReader reader, bool writeChildren, CancellationToken cancellationToken = default) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - return WriteTokenAsync(reader, writeChildren, true, true, cancellationToken); - } - - /// - /// Asynchronously writes the token and its value. - /// - /// The to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public Task WriteTokenAsync(JsonToken token, CancellationToken cancellationToken = default) - { - return WriteTokenAsync(token, null, cancellationToken); - } - - /// - /// Asynchronously writes the token and its value. - /// - /// The to write. - /// - /// The value to write. - /// A value is only required for tokens that have an associated value, e.g. the property name for . - /// null can be passed to the method for tokens that don't have a value, e.g. . - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - switch (token) - { - case JsonToken.None: - // read to next - return AsyncUtils.CompletedTask; - case JsonToken.StartObject: - return WriteStartObjectAsync(cancellationToken); - case JsonToken.StartArray: - return WriteStartArrayAsync(cancellationToken); - case JsonToken.StartConstructor: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WriteStartConstructorAsync(value.ToString(), cancellationToken); - case JsonToken.PropertyName: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WritePropertyNameAsync(value.ToString(), cancellationToken); - case JsonToken.Comment: - return WriteCommentAsync(value?.ToString(), cancellationToken); - case JsonToken.Integer: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return -#if HAVE_BIG_INTEGER - value is BigInteger integer ? WriteValueAsync(integer, cancellationToken) : -#endif - WriteValueAsync(Convert.ToInt64(value, CultureInfo.InvariantCulture), cancellationToken); - case JsonToken.Float: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is decimal dec) - { - return WriteValueAsync(dec, cancellationToken); - } - - if (value is double doub) - { - return WriteValueAsync(doub, cancellationToken); - } - - if (value is float f) - { - return WriteValueAsync(f, cancellationToken); - } - - return WriteValueAsync(Convert.ToDouble(value, CultureInfo.InvariantCulture), cancellationToken); - case JsonToken.String: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WriteValueAsync(value.ToString(), cancellationToken); - case JsonToken.Boolean: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WriteValueAsync(Convert.ToBoolean(value, CultureInfo.InvariantCulture), cancellationToken); - case JsonToken.Null: - return WriteNullAsync(cancellationToken); - case JsonToken.Undefined: - return WriteUndefinedAsync(cancellationToken); - case JsonToken.EndObject: - return WriteEndObjectAsync(cancellationToken); - case JsonToken.EndArray: - return WriteEndArrayAsync(cancellationToken); - case JsonToken.EndConstructor: - return WriteEndConstructorAsync(cancellationToken); - case JsonToken.Date: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is DateTimeOffset offset) - { - return WriteValueAsync(offset, cancellationToken); - } - - return WriteValueAsync(Convert.ToDateTime(value, CultureInfo.InvariantCulture), cancellationToken); - case JsonToken.Raw: - return WriteRawValueAsync(value?.ToString(), cancellationToken); - case JsonToken.Bytes: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is Guid guid) - { - return WriteValueAsync(guid, cancellationToken); - } - - return WriteValueAsync((byte[]?)value, cancellationToken); - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token), token, "Unexpected token type."); - } - } - - internal virtual async Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) - { - int initialDepth = CalculateWriteTokenInitialDepth(reader); - - do - { - // write a JValue date when the constructor is for a date - if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) - { - await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(false); - } - else - { - if (writeComments || reader.TokenType != JsonToken.Comment) - { - await WriteTokenAsync(reader.TokenType, reader.Value, cancellationToken).ConfigureAwait(false); - } - } - } while ( - // stop if we have reached the end of the token being read - initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) - && writeChildren - && await reader.ReadAsync(cancellationToken).ConfigureAwait(false)); - - if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) - { - throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); - } - } - - // For internal use, when we know the writer does not offer true async support (e.g. when backed - // by a StringWriter) and therefore async write methods are always in practice just a less efficient - // path through the sync version. - internal async Task WriteTokenSyncReadingAsync(JsonReader reader, CancellationToken cancellationToken) - { - int initialDepth = CalculateWriteTokenInitialDepth(reader); - - do - { - // write a JValue date when the constructor is for a date - if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) - { - WriteConstructorDate(reader); - } - else - { - WriteToken(reader.TokenType, reader.Value); - } - } while ( - // stop if we have reached the end of the token being read - initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) - && await reader.ReadAsync(cancellationToken).ConfigureAwait(false)); - - if (initialDepth < CalculateWriteTokenFinalDepth(reader)) - { - throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); - } - } - - private async Task WriteConstructorDateAsync(JsonReader reader, CancellationToken cancellationToken) - { - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); - } - if (reader.TokenType != JsonToken.Integer) - { - throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null); - } - - DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value!); - - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); - } - if (reader.TokenType != JsonToken.EndConstructor) - { - throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null); - } - - await WriteValueAsync(date, cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(bool value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(byte value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a [] value. - /// - /// The [] value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(char value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(char? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(double value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(double? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(float value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(float? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(int value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(int? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(long value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(long? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(short value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(short? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(uint value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a value. - /// - /// The value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes a of value. - /// - /// The of value to write. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - - public virtual Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteValue(value); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes an undefined value. - /// - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteUndefinedAsync(CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteUndefined(); - return AsyncUtils.CompletedTask; - } - - /// - /// Asynchronously writes the given white space. - /// - /// The string of white space characters. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - WriteWhitespace(ws); - return AsyncUtils.CompletedTask; - } - - internal Task InternalWriteValueAsync(JsonToken token, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - UpdateScopeWithFinishedValue(); - return AutoCompleteAsync(token, cancellationToken); - } - - /// - /// Asynchronously ets the state of the . - /// - /// The being written. - /// The value being written. - /// The token to monitor for cancellation requests. The default value is . - /// A that represents the asynchronous operation. - /// The default behaviour is to execute synchronously, returning an already-completed task. Derived - /// classes can override this behaviour for true asynchronicity. - protected Task SetWriteStateAsync(JsonToken token, object value, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - switch (token) - { - case JsonToken.StartObject: - return InternalWriteStartAsync(token, JsonContainerType.Object, cancellationToken); - case JsonToken.StartArray: - return InternalWriteStartAsync(token, JsonContainerType.Array, cancellationToken); - case JsonToken.StartConstructor: - return InternalWriteStartAsync(token, JsonContainerType.Constructor, cancellationToken); - case JsonToken.PropertyName: - if (!(value is string s)) - { - throw new ArgumentException("A name is required when setting property name state.", nameof(value)); - } - - return InternalWritePropertyNameAsync(s, cancellationToken); - case JsonToken.Comment: - return InternalWriteCommentAsync(cancellationToken); - case JsonToken.Raw: - return AsyncUtils.CompletedTask; - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.String: - case JsonToken.Boolean: - case JsonToken.Date: - case JsonToken.Bytes: - case JsonToken.Null: - case JsonToken.Undefined: - return InternalWriteValueAsync(token, cancellationToken); - case JsonToken.EndObject: - return InternalWriteEndAsync(JsonContainerType.Object, cancellationToken); - case JsonToken.EndArray: - return InternalWriteEndAsync(JsonContainerType.Array, cancellationToken); - case JsonToken.EndConstructor: - return InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken); - default: - throw new ArgumentOutOfRangeException(nameof(token)); - } - } - - internal static Task WriteValueAsync(JsonWriter writer, PrimitiveTypeCode typeCode, object value, CancellationToken cancellationToken) - { - while (true) - { - switch (typeCode) - { - case PrimitiveTypeCode.Char: - return writer.WriteValueAsync((char)value, cancellationToken); - case PrimitiveTypeCode.CharNullable: - return writer.WriteValueAsync(value == null ? (char?)null : (char)value, cancellationToken); - case PrimitiveTypeCode.Boolean: - return writer.WriteValueAsync((bool)value, cancellationToken); - case PrimitiveTypeCode.BooleanNullable: - return writer.WriteValueAsync(value == null ? (bool?)null : (bool)value, cancellationToken); - case PrimitiveTypeCode.SByte: - return writer.WriteValueAsync((sbyte)value, cancellationToken); - case PrimitiveTypeCode.SByteNullable: - return writer.WriteValueAsync(value == null ? (sbyte?)null : (sbyte)value, cancellationToken); - case PrimitiveTypeCode.Int16: - return writer.WriteValueAsync((short)value, cancellationToken); - case PrimitiveTypeCode.Int16Nullable: - return writer.WriteValueAsync(value == null ? (short?)null : (short)value, cancellationToken); - case PrimitiveTypeCode.UInt16: - return writer.WriteValueAsync((ushort)value, cancellationToken); - case PrimitiveTypeCode.UInt16Nullable: - return writer.WriteValueAsync(value == null ? (ushort?)null : (ushort)value, cancellationToken); - case PrimitiveTypeCode.Int32: - return writer.WriteValueAsync((int)value, cancellationToken); - case PrimitiveTypeCode.Int32Nullable: - return writer.WriteValueAsync(value == null ? (int?)null : (int)value, cancellationToken); - case PrimitiveTypeCode.Byte: - return writer.WriteValueAsync((byte)value, cancellationToken); - case PrimitiveTypeCode.ByteNullable: - return writer.WriteValueAsync(value == null ? (byte?)null : (byte)value, cancellationToken); - case PrimitiveTypeCode.UInt32: - return writer.WriteValueAsync((uint)value, cancellationToken); - case PrimitiveTypeCode.UInt32Nullable: - return writer.WriteValueAsync(value == null ? (uint?)null : (uint)value, cancellationToken); - case PrimitiveTypeCode.Int64: - return writer.WriteValueAsync((long)value, cancellationToken); - case PrimitiveTypeCode.Int64Nullable: - return writer.WriteValueAsync(value == null ? (long?)null : (long)value, cancellationToken); - case PrimitiveTypeCode.UInt64: - return writer.WriteValueAsync((ulong)value, cancellationToken); - case PrimitiveTypeCode.UInt64Nullable: - return writer.WriteValueAsync(value == null ? (ulong?)null : (ulong)value, cancellationToken); - case PrimitiveTypeCode.Single: - return writer.WriteValueAsync((float)value, cancellationToken); - case PrimitiveTypeCode.SingleNullable: - return writer.WriteValueAsync(value == null ? (float?)null : (float)value, cancellationToken); - case PrimitiveTypeCode.Double: - return writer.WriteValueAsync((double)value, cancellationToken); - case PrimitiveTypeCode.DoubleNullable: - return writer.WriteValueAsync(value == null ? (double?)null : (double)value, cancellationToken); - case PrimitiveTypeCode.DateTime: - return writer.WriteValueAsync((DateTime)value, cancellationToken); - case PrimitiveTypeCode.DateTimeNullable: - return writer.WriteValueAsync(value == null ? (DateTime?)null : (DateTime)value, cancellationToken); - case PrimitiveTypeCode.DateTimeOffset: - return writer.WriteValueAsync((DateTimeOffset)value, cancellationToken); - case PrimitiveTypeCode.DateTimeOffsetNullable: - return writer.WriteValueAsync(value == null ? (DateTimeOffset?)null : (DateTimeOffset)value, cancellationToken); - case PrimitiveTypeCode.Decimal: - return writer.WriteValueAsync((decimal)value, cancellationToken); - case PrimitiveTypeCode.DecimalNullable: - return writer.WriteValueAsync(value == null ? (decimal?)null : (decimal)value, cancellationToken); - case PrimitiveTypeCode.Guid: - return writer.WriteValueAsync((Guid)value, cancellationToken); - case PrimitiveTypeCode.GuidNullable: - return writer.WriteValueAsync(value == null ? (Guid?)null : (Guid)value, cancellationToken); - case PrimitiveTypeCode.TimeSpan: - return writer.WriteValueAsync((TimeSpan)value, cancellationToken); - case PrimitiveTypeCode.TimeSpanNullable: - return writer.WriteValueAsync(value == null ? (TimeSpan?)null : (TimeSpan)value, cancellationToken); -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigInteger: - - // this will call to WriteValueAsync(object) - return writer.WriteValueAsync((BigInteger)value, cancellationToken); - case PrimitiveTypeCode.BigIntegerNullable: - - // this will call to WriteValueAsync(object) - return writer.WriteValueAsync(value == null ? (BigInteger?)null : (BigInteger)value, cancellationToken); -#endif - case PrimitiveTypeCode.Uri: - return writer.WriteValueAsync((Uri)value, cancellationToken); - case PrimitiveTypeCode.String: - return writer.WriteValueAsync((string)value, cancellationToken); - case PrimitiveTypeCode.Bytes: - return writer.WriteValueAsync((byte[])value, cancellationToken); -#if HAVE_DB_NULL_TYPE_CODE - case PrimitiveTypeCode.DBNull: - return writer.WriteNullAsync(cancellationToken); -#endif - default: -#if HAVE_ICONVERTIBLE - if (value is IConvertible convertible) - { - ResolveConvertibleValue(convertible, out typeCode, out value); - continue; - } -#endif - - // write an unknown null value, fix https://github.com/JamesNK/Newtonsoft.Json/issues/1460 - if (value == null) - { - return writer.WriteNullAsync(cancellationToken); - } - - throw CreateUnsupportedTypeException(writer, value); - } - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.cs deleted file mode 100644 index 0540fb241..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriter.cs +++ /dev/null @@ -1,1547 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. - /// - internal abstract partial class JsonWriter : IDisposable - { - internal enum State - { - Start = 0, - Property = 1, - ObjectStart = 2, - Object = 3, - ArrayStart = 4, - Array = 5, - ConstructorStart = 6, - Constructor = 7, - Closed = 8, - Error = 9 - } - - // array that gives a new state based on the current state an the token being written - private static readonly State[][] StateArray; - - internal static readonly State[][] StateArrayTemplate = - { - // Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error - // - /* None */ - new[] - { - State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error - }, - /* StartObject */ - new[] - { - State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, - State.ObjectStart, State.Error, State.Error - }, - /* StartArray */ - new[] - { - State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, - State.ArrayStart, State.Error, State.Error - }, - /* StartConstructor */ - new[] - { - State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, - State.ConstructorStart, State.ConstructorStart, State.Error, State.Error - }, - /* Property */ - new[] - { - State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, - State.Error - }, - /* Comment */ - new[] - { - State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, - State.Error, State.Error - }, - /* Raw */ - new[] - { - State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, - State.Error, State.Error - }, - /* Value (this will be copied) */ - new[] - { - State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, - State.Error - } - }; - - internal static State[][] BuildStateArray() - { - var allStates = StateArrayTemplate.ToList(); - var errorStates = StateArrayTemplate[0]; - var valueStates = StateArrayTemplate[7]; - - var enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken)); - - foreach (var valueToken in enumValuesAndNames.Values) - { - if (allStates.Count <= (int)valueToken) - { - var token = (JsonToken)valueToken; - switch (token) - { - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.String: - case JsonToken.Boolean: - case JsonToken.Null: - case JsonToken.Undefined: - case JsonToken.Date: - case JsonToken.Bytes: - allStates.Add(valueStates); - break; - default: - allStates.Add(errorStates); - break; - } - } - } - - return allStates.ToArray(); - } - - static JsonWriter() => StateArray = BuildStateArray(); - - private List? _stack; - private JsonPosition _currentPosition; - private State _currentState; - private Formatting _formatting; - - /// - /// Gets or sets a value indicating whether the destination should be closed when this writer is closed. - /// - /// - /// true to close the destination when this writer is closed; otherwise false. The default is true. - /// - public bool CloseOutput { get; set; } - - /// - /// Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed. - /// - /// - /// true to auto-complete the JSON when this writer is closed; otherwise false. The default is true. - /// - public bool AutoCompleteOnClose { get; set; } - - /// - /// Gets the top. - /// - /// The top. - protected internal int Top - { - get - { - var depth = _stack?.Count ?? 0; - if (Peek() != JsonContainerType.None) depth++; - - return depth; - } - } - - /// - /// Gets the state of the writer. - /// - public WriteState WriteState - { - get - { - switch (_currentState) - { - case State.Error: - return WriteState.Error; - case State.Closed: - return WriteState.Closed; - case State.Object: - case State.ObjectStart: - return WriteState.Object; - case State.Array: - case State.ArrayStart: - return WriteState.Array; - case State.Constructor: - case State.ConstructorStart: - return WriteState.Constructor; - case State.Property: - return WriteState.Property; - case State.Start: - return WriteState.Start; - default: - throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null); - } - } - } - - internal string ContainerPath - { - get - { - if (_currentPosition.Type == JsonContainerType.None || _stack == null) return string.Empty; - - return JsonPosition.BuildPath(_stack, null); - } - } - - /// - /// Gets the path of the writer. - /// - public string Path - { - get - { - if (_currentPosition.Type == JsonContainerType.None) return string.Empty; - - var insideContainer = _currentState != State.ArrayStart - && _currentState != State.ConstructorStart - && _currentState != State.ObjectStart; - - var current = insideContainer ? (JsonPosition?)_currentPosition : null; - - return JsonPosition.BuildPath(_stack!, current); - } - } - - private DateFormatHandling _dateFormatHandling; - private DateTimeZoneHandling _dateTimeZoneHandling; - private StringEscapeHandling _stringEscapeHandling; - private FloatFormatHandling _floatFormatHandling; - private CultureInfo? _culture; - - /// - /// Gets or sets a value indicating how JSON text output should be formatted. - /// - public Formatting Formatting - { - get => _formatting; - set - { - if (value < Formatting.None || value > Formatting.Indented) throw new ArgumentOutOfRangeException(nameof(value)); - - _formatting = value; - } - } - - /// - /// Gets or sets how dates are written to JSON text. - /// - public DateFormatHandling DateFormatHandling - { - get => _dateFormatHandling; - set - { - if (value < DateFormatHandling.IsoDateFormat || value > DateFormatHandling.MicrosoftDateFormat) - throw new ArgumentOutOfRangeException(nameof(value)); - - _dateFormatHandling = value; - } - } - - /// - /// Gets or sets how time zones are handled when writing JSON text. - /// - public DateTimeZoneHandling DateTimeZoneHandling - { - get => _dateTimeZoneHandling; - set - { - if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) - throw new ArgumentOutOfRangeException(nameof(value)); - - _dateTimeZoneHandling = value; - } - } - - /// - /// Gets or sets how strings are escaped when writing JSON text. - /// - public StringEscapeHandling StringEscapeHandling - { - get => _stringEscapeHandling; - set - { - if (value < StringEscapeHandling.Default || value > StringEscapeHandling.EscapeHtml) - throw new ArgumentOutOfRangeException(nameof(value)); - - _stringEscapeHandling = value; - OnStringEscapeHandlingChanged(); - } - } - - internal virtual void OnStringEscapeHandlingChanged() - { - // hacky but there is a calculated value that relies on StringEscapeHandling - } - - /// - /// Gets or sets how special floating point numbers, e.g. , - /// and , - /// are written to JSON text. - /// - public FloatFormatHandling FloatFormatHandling - { - get => _floatFormatHandling; - set - { - if (value < FloatFormatHandling.String || value > FloatFormatHandling.DefaultValue) - throw new ArgumentOutOfRangeException(nameof(value)); - - _floatFormatHandling = value; - } - } - - /// - /// Gets or sets how and values are formatted when writing JSON text. - /// - public string? DateFormatString { get; set; } - - /// - /// Gets or sets the culture used when writing JSON. Defaults to . - /// - public CultureInfo Culture - { - get => _culture ?? CultureInfo.InvariantCulture; - set => _culture = value; - } - - /// - /// Initializes a new instance of the class. - /// - protected JsonWriter() - { - _currentState = State.Start; - _formatting = Formatting.None; - _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; - - CloseOutput = true; - AutoCompleteOnClose = true; - } - - internal void UpdateScopeWithFinishedValue() - { - if (_currentPosition.HasIndex) _currentPosition.Position++; - } - - private void Push(JsonContainerType value) - { - if (_currentPosition.Type != JsonContainerType.None) - { - if (_stack == null) _stack = new List(); - - _stack.Add(_currentPosition); - } - - _currentPosition = new JsonPosition(value); - } - - private JsonContainerType Pop() - { - var oldPosition = _currentPosition; - - if (_stack != null && _stack.Count > 0) - { - _currentPosition = _stack[_stack.Count - 1]; - _stack.RemoveAt(_stack.Count - 1); - } - else - _currentPosition = new JsonPosition(); - - return oldPosition.Type; - } - - private JsonContainerType Peek() => _currentPosition.Type; - - /// - /// Flushes whatever is in the buffer to the destination and also flushes the destination. - /// - public abstract void Flush(); - - /// - /// Closes this writer. - /// If is set to true, the destination is also closed. - /// If is set to true, the JSON is auto-completed. - /// - public virtual void Close() - { - if (AutoCompleteOnClose) AutoCompleteAll(); - } - - /// - /// Writes the beginning of a JSON object. - /// - public virtual void WriteStartObject() => InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); - - /// - /// Writes the end of a JSON object. - /// - public virtual void WriteEndObject() => InternalWriteEnd(JsonContainerType.Object); - - /// - /// Writes the beginning of a JSON array. - /// - public virtual void WriteStartArray() => InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); - - /// - /// Writes the end of an array. - /// - public virtual void WriteEndArray() => InternalWriteEnd(JsonContainerType.Array); - - /// - /// Writes the start of a constructor with the given name. - /// - /// The name of the constructor. - public virtual void WriteStartConstructor(string name) => InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); - - /// - /// Writes the end constructor. - /// - public virtual void WriteEndConstructor() => InternalWriteEnd(JsonContainerType.Constructor); - - /// - /// Writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - public virtual void WritePropertyName(string name) => InternalWritePropertyName(name); - - /// - /// Writes the property name of a name/value pair of a JSON object. - /// - /// The name of the property. - /// A flag to indicate whether the text should be escaped when it is written as a JSON property name. - public virtual void WritePropertyName(string name, bool escape) => WritePropertyName(name); - - /// - /// Writes the end of the current JSON object or array. - /// - public virtual void WriteEnd() => WriteEnd(Peek()); - - /// - /// Writes the current token and its children. - /// - /// The to read the token from. - public void WriteToken(JsonReader reader) => WriteToken(reader, true); - - /// - /// Writes the current token. - /// - /// The to read the token from. - /// A flag indicating whether the current token's children should be written. - public void WriteToken(JsonReader reader, bool writeChildren) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - WriteToken(reader, writeChildren, true, true); - } - - /// - /// Writes the token and its value. - /// - /// The to write. - /// - /// The value to write. - /// A value is only required for tokens that have an associated value, e.g. the property name for - /// . - /// null can be passed to the method for tokens that don't have a value, e.g. . - /// - public void WriteToken(JsonToken token, object? value) - { - switch (token) - { - case JsonToken.None: - // read to next - break; - case JsonToken.StartObject: - WriteStartObject(); - break; - case JsonToken.StartArray: - WriteStartArray(); - break; - case JsonToken.StartConstructor: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - WriteStartConstructor(value.ToString()); - break; - case JsonToken.PropertyName: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - WritePropertyName(value.ToString()); - break; - case JsonToken.Comment: - WriteComment(value?.ToString()); - break; - case JsonToken.Integer: - ValidationUtils.ArgumentNotNull(value, nameof(value)); -#if HAVE_BIG_INTEGER - if (value is BigInteger integer) - { - WriteValue(integer); - } - else -#endif - { - WriteValue(Convert.ToInt64(value, CultureInfo.InvariantCulture)); - } - break; - case JsonToken.Float: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is decimal decimalValue) - WriteValue(decimalValue); - else if (value is double doubleValue) - WriteValue(doubleValue); - else if (value is float floatValue) - WriteValue(floatValue); - else - WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture)); - break; - case JsonToken.String: - // Allow for a null string. This matches JTokenReader behavior which can read - // a JsonToken.String with a null value. - WriteValue(value?.ToString()); - break; - case JsonToken.Boolean: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - WriteValue(Convert.ToBoolean(value, CultureInfo.InvariantCulture)); - break; - case JsonToken.Null: - WriteNull(); - break; - case JsonToken.Undefined: - WriteUndefined(); - break; - case JsonToken.EndObject: - WriteEndObject(); - break; - case JsonToken.EndArray: - WriteEndArray(); - break; - case JsonToken.EndConstructor: - WriteEndConstructor(); - break; - case JsonToken.Date: - ValidationUtils.ArgumentNotNull(value, nameof(value)); -#if HAVE_DATE_TIME_OFFSET - if (value is DateTimeOffset dt) - { - WriteValue(dt); - } - else -#endif - { - WriteValue(Convert.ToDateTime(value, CultureInfo.InvariantCulture)); - } - break; - case JsonToken.Raw: - WriteRawValue(value?.ToString()); - break; - case JsonToken.Bytes: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is Guid guid) - WriteValue(guid); - else - WriteValue((byte[])value!); - break; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token), token, "Unexpected token type."); - } - } - - /// - /// Writes the token. - /// - /// The to write. - public void WriteToken(JsonToken token) => WriteToken(token, null); - - internal virtual void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) - { - var initialDepth = CalculateWriteTokenInitialDepth(reader); - - do - // write a JValue date when the constructor is for a date - if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor - && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) - WriteConstructorDate(reader); - else - { - if (writeComments || reader.TokenType != JsonToken.Comment) WriteToken(reader.TokenType, reader.Value); - } - while ( - // stop if we have reached the end of the token being read - initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) - && writeChildren - && reader.Read()); - - if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) - throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); - } - - private bool IsWriteTokenIncomplete(JsonReader reader, bool writeChildren, int initialDepth) - { - var finalDepth = CalculateWriteTokenFinalDepth(reader); - return initialDepth < finalDepth || - writeChildren && initialDepth == finalDepth && JsonTokenUtils.IsStartToken(reader.TokenType); - } - - private int CalculateWriteTokenInitialDepth(JsonReader reader) - { - var type = reader.TokenType; - if (type == JsonToken.None) return -1; - - return JsonTokenUtils.IsStartToken(type) ? reader.Depth : reader.Depth + 1; - } - - private int CalculateWriteTokenFinalDepth(JsonReader reader) - { - var type = reader.TokenType; - if (type == JsonToken.None) return -1; - - return JsonTokenUtils.IsEndToken(type) ? reader.Depth - 1 : reader.Depth; - } - - private void WriteConstructorDate(JsonReader reader) - { - if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out var dateTime, out var errorMessage)) - throw JsonWriterException.Create(this, errorMessage, null); - - WriteValue(dateTime); - } - - private void WriteEnd(JsonContainerType type) - { - switch (type) - { - case JsonContainerType.Object: - WriteEndObject(); - break; - case JsonContainerType.Array: - WriteEndArray(); - break; - case JsonContainerType.Constructor: - WriteEndConstructor(); - break; - default: - throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null); - } - } - - private void AutoCompleteAll() - { - while (Top > 0) WriteEnd(); - } - - private JsonToken GetCloseTokenForType(JsonContainerType type) - { - switch (type) - { - case JsonContainerType.Object: - return JsonToken.EndObject; - case JsonContainerType.Array: - return JsonToken.EndArray; - case JsonContainerType.Constructor: - return JsonToken.EndConstructor; - default: - throw JsonWriterException.Create(this, "No close token for type: " + type, null); - } - } - - private void AutoCompleteClose(JsonContainerType type) - { - var levelsToComplete = CalculateLevelsToComplete(type); - - for (var i = 0; i < levelsToComplete; i++) - { - var token = GetCloseTokenForType(Pop()); - - if (_currentState == State.Property) WriteNull(); - - if (_formatting == Formatting.Indented) - if (_currentState != State.ObjectStart && _currentState != State.ArrayStart) - WriteIndent(); - - WriteEnd(token); - - UpdateCurrentState(); - } - } - - private int CalculateLevelsToComplete(JsonContainerType type) - { - var levelsToComplete = 0; - - if (_currentPosition.Type == type) - levelsToComplete = 1; - else - { - var top = Top - 2; - for (var i = top; i >= 0; i--) - { - var currentLevel = top - i; - - if (_stack![currentLevel].Type == type) - { - levelsToComplete = i + 2; - break; - } - } - } - - if (levelsToComplete == 0) throw JsonWriterException.Create(this, "No token to close.", null); - - return levelsToComplete; - } - - private void UpdateCurrentState() - { - var currentLevelType = Peek(); - - switch (currentLevelType) - { - case JsonContainerType.Object: - _currentState = State.Object; - break; - case JsonContainerType.Array: - _currentState = State.Array; - break; - case JsonContainerType.Constructor: - _currentState = State.Array; - break; - case JsonContainerType.None: - _currentState = State.Start; - break; - default: - throw JsonWriterException.Create(this, "Unknown JsonType: " + currentLevelType, null); - } - } - - /// - /// Writes the specified end token. - /// - /// The end token to write. - protected virtual void WriteEnd(JsonToken token) { } - - /// - /// Writes indent characters. - /// - protected virtual void WriteIndent() { } - - /// - /// Writes the JSON value delimiter. - /// - protected virtual void WriteValueDelimiter() { } - - /// - /// Writes an indent space. - /// - protected virtual void WriteIndentSpace() { } - - internal void AutoComplete(JsonToken tokenBeingWritten) - { - // gets new state based on the current state and what is being written - var newState = StateArray[(int)tokenBeingWritten][(int)_currentState]; - - if (newState == State.Error) - throw JsonWriterException.Create(this, - "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, - tokenBeingWritten.ToString(), _currentState.ToString()), null); - - if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) - && tokenBeingWritten != JsonToken.Comment) WriteValueDelimiter(); - - if (_formatting == Formatting.Indented) - { - if (_currentState == State.Property) WriteIndentSpace(); - - // don't indent a property when it is the first token to be written (i.e. at the start) - if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.Constructor - || _currentState == State.ConstructorStart - || tokenBeingWritten == JsonToken.PropertyName && _currentState != State.Start) - WriteIndent(); - } - - _currentState = newState; - } - - #region WriteValue methods - - /// - /// Writes a null value. - /// - public virtual void WriteNull() => InternalWriteValue(JsonToken.Null); - - /// - /// Writes an undefined value. - /// - public virtual void WriteUndefined() => InternalWriteValue(JsonToken.Undefined); - - /// - /// Writes raw JSON without changing the writer's state. - /// - /// The raw JSON to write. - public virtual void WriteRaw(string? json) => InternalWriteRaw(); - - /// - /// Writes raw JSON where a value is expected and updates the writer's state. - /// - /// The raw JSON to write. - public virtual void WriteRawValue(string? json) - { - // hack. want writer to change state as if a value had been written - UpdateScopeWithFinishedValue(); - AutoComplete(JsonToken.Undefined); - WriteRaw(json); - } - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(string? value) => InternalWriteValue(JsonToken.String); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(int value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - - public virtual void WriteValue(uint value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(long value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - - public virtual void WriteValue(ulong value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(float value) => InternalWriteValue(JsonToken.Float); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(double value) => InternalWriteValue(JsonToken.Float); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(bool value) => InternalWriteValue(JsonToken.Boolean); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(short value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - - public virtual void WriteValue(ushort value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(char value) => InternalWriteValue(JsonToken.String); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(byte value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - - public virtual void WriteValue(sbyte value) => InternalWriteValue(JsonToken.Integer); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(decimal value) => InternalWriteValue(JsonToken.Float); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(DateTime value) => InternalWriteValue(JsonToken.Date); - -#if HAVE_DATE_TIME_OFFSET - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(DateTimeOffset value) - { - InternalWriteValue(JsonToken.Date); - } -#endif - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(Guid value) => InternalWriteValue(JsonToken.String); - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(TimeSpan value) => InternalWriteValue(JsonToken.String); - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(int? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - - public virtual void WriteValue(uint? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(long? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - - public virtual void WriteValue(ulong? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(float? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(double? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(bool? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(short? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - - public virtual void WriteValue(ushort? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(char? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(byte? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - - public virtual void WriteValue(sbyte? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(decimal? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(DateTime? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(DateTimeOffset? value) - { - if (value == null) - { - WriteNull(); - } - else - { - WriteValue(value.GetValueOrDefault()); - } - } -#endif - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(Guid? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a of value. - /// - /// The of value to write. - public virtual void WriteValue(TimeSpan? value) - { - if (value == null) - WriteNull(); - else - WriteValue(value.GetValueOrDefault()); - } - - /// - /// Writes a [] value. - /// - /// The [] value to write. - public virtual void WriteValue(byte[]? value) - { - if (value == null) - WriteNull(); - else - InternalWriteValue(JsonToken.Bytes); - } - - /// - /// Writes a value. - /// - /// The value to write. - public virtual void WriteValue(Uri? value) - { - if (value == null) - WriteNull(); - else - InternalWriteValue(JsonToken.String); - } - - /// - /// Writes a value. - /// An error will raised if the value cannot be written as a single JSON token. - /// - /// The value to write. - public virtual void WriteValue(object? value) - { - if (value == null) - WriteNull(); - else - { -#if HAVE_BIG_INTEGER - // this is here because adding a WriteValue(BigInteger) to JsonWriter will - // mean the user has to add a reference to System.Numerics.dll - if (value is BigInteger) - { - throw CreateUnsupportedTypeException(this, value); - } -#endif - - WriteValue(this, ConvertUtils.GetTypeCode(value.GetType()), value); - } - } - - #endregion - - /// - /// Writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - public virtual void WriteComment(string? text) => InternalWriteComment(); - - /// - /// Writes the given white space. - /// - /// The string of white space characters. - public virtual void WriteWhitespace(string ws) => InternalWriteWhitespace(ws); - - void IDisposable.Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// true to release both managed and unmanaged resources; false to release only - /// unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (_currentState != State.Closed && disposing) Close(); - } - - internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value) - { - while (true) - { - switch (typeCode) - { - case PrimitiveTypeCode.Char: - writer.WriteValue((char)value); - return; - - case PrimitiveTypeCode.CharNullable: - writer.WriteValue(value == null ? (char?)null : (char)value); - return; - - case PrimitiveTypeCode.Boolean: - writer.WriteValue((bool)value); - return; - - case PrimitiveTypeCode.BooleanNullable: - writer.WriteValue(value == null ? (bool?)null : (bool)value); - return; - - case PrimitiveTypeCode.SByte: - writer.WriteValue((sbyte)value); - return; - - case PrimitiveTypeCode.SByteNullable: - writer.WriteValue(value == null ? (sbyte?)null : (sbyte)value); - return; - - case PrimitiveTypeCode.Int16: - writer.WriteValue((short)value); - return; - - case PrimitiveTypeCode.Int16Nullable: - writer.WriteValue(value == null ? (short?)null : (short)value); - return; - - case PrimitiveTypeCode.UInt16: - writer.WriteValue((ushort)value); - return; - - case PrimitiveTypeCode.UInt16Nullable: - writer.WriteValue(value == null ? (ushort?)null : (ushort)value); - return; - - case PrimitiveTypeCode.Int32: - writer.WriteValue((int)value); - return; - - case PrimitiveTypeCode.Int32Nullable: - writer.WriteValue(value == null ? (int?)null : (int)value); - return; - - case PrimitiveTypeCode.Byte: - writer.WriteValue((byte)value); - return; - - case PrimitiveTypeCode.ByteNullable: - writer.WriteValue(value == null ? (byte?)null : (byte)value); - return; - - case PrimitiveTypeCode.UInt32: - writer.WriteValue((uint)value); - return; - - case PrimitiveTypeCode.UInt32Nullable: - writer.WriteValue(value == null ? (uint?)null : (uint)value); - return; - - case PrimitiveTypeCode.Int64: - writer.WriteValue((long)value); - return; - - case PrimitiveTypeCode.Int64Nullable: - writer.WriteValue(value == null ? (long?)null : (long)value); - return; - - case PrimitiveTypeCode.UInt64: - writer.WriteValue((ulong)value); - return; - - case PrimitiveTypeCode.UInt64Nullable: - writer.WriteValue(value == null ? (ulong?)null : (ulong)value); - return; - - case PrimitiveTypeCode.Single: - writer.WriteValue((float)value); - return; - - case PrimitiveTypeCode.SingleNullable: - writer.WriteValue(value == null ? (float?)null : (float)value); - return; - - case PrimitiveTypeCode.Double: - writer.WriteValue((double)value); - return; - - case PrimitiveTypeCode.DoubleNullable: - writer.WriteValue(value == null ? (double?)null : (double)value); - return; - - case PrimitiveTypeCode.DateTime: - writer.WriteValue((DateTime)value); - return; - - case PrimitiveTypeCode.DateTimeNullable: - writer.WriteValue(value == null ? (DateTime?)null : (DateTime)value); - return; - -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: - writer.WriteValue((DateTimeOffset)value); - return; - - case PrimitiveTypeCode.DateTimeOffsetNullable: - writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value); - return; -#endif - case PrimitiveTypeCode.Decimal: - writer.WriteValue((decimal)value); - return; - - case PrimitiveTypeCode.DecimalNullable: - writer.WriteValue(value == null ? (decimal?)null : (decimal)value); - return; - - case PrimitiveTypeCode.Guid: - writer.WriteValue((Guid)value); - return; - - case PrimitiveTypeCode.GuidNullable: - writer.WriteValue(value == null ? (Guid?)null : (Guid)value); - return; - - case PrimitiveTypeCode.TimeSpan: - writer.WriteValue((TimeSpan)value); - return; - - case PrimitiveTypeCode.TimeSpanNullable: - writer.WriteValue(value == null ? (TimeSpan?)null : (TimeSpan)value); - return; - -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigInteger: - // this will call to WriteValue(object) - writer.WriteValue((BigInteger)value); - return; - - case PrimitiveTypeCode.BigIntegerNullable: - // this will call to WriteValue(object) - writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value); - return; -#endif - case PrimitiveTypeCode.Uri: - writer.WriteValue((Uri)value); - return; - - case PrimitiveTypeCode.String: - writer.WriteValue((string)value); - return; - - case PrimitiveTypeCode.Bytes: - writer.WriteValue((byte[])value); - return; - -#if HAVE_DB_NULL_TYPE_CODE - case PrimitiveTypeCode.DBNull: - writer.WriteNull(); - return; -#endif - default: -#if HAVE_ICONVERTIBLE - if (value is IConvertible convertible) - { - ResolveConvertibleValue(convertible, out typeCode, out value); - continue; - } -#endif - - // write an unknown null value, fix https://github.com/JamesNK/Newtonsoft.Json/issues/1460 - if (value == null) - { - writer.WriteNull(); - return; - } - - throw CreateUnsupportedTypeException(writer, value); - } - } - } - -#if HAVE_ICONVERTIBLE - private static void ResolveConvertibleValue(IConvertible convertible, out PrimitiveTypeCode typeCode, out object value) - { - // the value is a non-standard IConvertible - // convert to the underlying value and retry - TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertible); - - // if convertible has an underlying typecode of Object then attempt to convert it to a string - typeCode = typeInformation.TypeCode == PrimitiveTypeCode.Object ? PrimitiveTypeCode.String : typeInformation.TypeCode; - Type resolvedType = typeInformation.TypeCode == PrimitiveTypeCode.Object ? typeof(string) : typeInformation.Type; - value = convertible.ToType(resolvedType, CultureInfo.InvariantCulture); - } -#endif - - private static JsonWriterException CreateUnsupportedTypeException(JsonWriter writer, object value) => JsonWriterException.Create(writer, - "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, - value.GetType()), null); - - /// - /// Sets the state of the . - /// - /// The being written. - /// The value being written. - protected void SetWriteState(JsonToken token, object value) - { - switch (token) - { - case JsonToken.StartObject: - InternalWriteStart(token, JsonContainerType.Object); - break; - case JsonToken.StartArray: - InternalWriteStart(token, JsonContainerType.Array); - break; - case JsonToken.StartConstructor: - InternalWriteStart(token, JsonContainerType.Constructor); - break; - case JsonToken.PropertyName: - if (!(value is string s)) throw new ArgumentException("A name is required when setting property name state.", nameof(value)); - - InternalWritePropertyName(s); - break; - case JsonToken.Comment: - InternalWriteComment(); - break; - case JsonToken.Raw: - InternalWriteRaw(); - break; - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.String: - case JsonToken.Boolean: - case JsonToken.Date: - case JsonToken.Bytes: - case JsonToken.Null: - case JsonToken.Undefined: - InternalWriteValue(token); - break; - case JsonToken.EndObject: - InternalWriteEnd(JsonContainerType.Object); - break; - case JsonToken.EndArray: - InternalWriteEnd(JsonContainerType.Array); - break; - case JsonToken.EndConstructor: - InternalWriteEnd(JsonContainerType.Constructor); - break; - default: - throw new ArgumentOutOfRangeException(nameof(token)); - } - } - - internal void InternalWriteEnd(JsonContainerType container) => AutoCompleteClose(container); - - internal void InternalWritePropertyName(string name) - { - _currentPosition.PropertyName = name; - AutoComplete(JsonToken.PropertyName); - } - - internal void InternalWriteRaw() { } - - internal void InternalWriteStart(JsonToken token, JsonContainerType container) - { - UpdateScopeWithFinishedValue(); - AutoComplete(token); - Push(container); - } - - internal void InternalWriteValue(JsonToken token) - { - UpdateScopeWithFinishedValue(); - AutoComplete(token); - } - - internal void InternalWriteWhitespace(string ws) - { - if (ws != null) - if (!StringUtils.IsWhiteSpace(ws)) - throw JsonWriterException.Create(this, "Only white space characters should be used.", null); - } - - internal void InternalWriteComment() => AutoComplete(JsonToken.Comment); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriterException.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriterException.cs deleted file mode 100644 index d895e5486..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonWriterException.cs +++ /dev/null @@ -1,110 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// The exception thrown when an error occurs while writing JSON text. - /// -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - [Serializable] -#endif - internal class JsonWriterException : JsonException - { - /// - /// Gets the path to the JSON where the error occurred. - /// - /// The path to the JSON where the error occurred. - public string? Path { get; } - - /// - /// Initializes a new instance of the class. - /// - public JsonWriterException() { } - - /// - /// Initializes a new instance of the class - /// with a specified error message. - /// - /// The error message that explains the reason for the exception. - public JsonWriterException(string message) - : base(message) { } - - /// - /// Initializes a new instance of the class - /// with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonWriterException(string message, Exception innerException) - : base(message, innerException) { } - -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// The parameter is null. - /// The class name is null or is zero (0). - public JsonWriterException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } -#endif - - /// - /// Initializes a new instance of the class - /// with a specified error message, JSON path and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The path to the JSON where the error occurred. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonWriterException(string message, string path, Exception? innerException) - : base(message, innerException) => - Path = path; - - internal static JsonWriterException Create(JsonWriter writer, string message, Exception? ex) => Create(writer.ContainerPath, message, ex); - - internal static JsonWriterException Create(string path, string message, Exception? ex) - { - message = JsonPosition.FormatMessage(null, path, message); - - return new JsonWriterException(message, path, ex); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/CommentHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/CommentHandling.cs deleted file mode 100644 index dfac7b670..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/CommentHandling.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies how JSON comments are handled when loading JSON. - /// - internal enum CommentHandling - { - /// - /// Ignore comments. - /// - Ignore = 0, - - /// - /// Load comments as a with type . - /// - Load = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/DuplicatePropertyNameHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/DuplicatePropertyNameHandling.cs deleted file mode 100644 index 1af1e1268..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/DuplicatePropertyNameHandling.cs +++ /dev/null @@ -1,53 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies how duplicate property names are handled when loading JSON. - /// - internal enum DuplicatePropertyNameHandling - { - /// - /// Replace the existing value when there is a duplicate property. The value of the last property in the JSON object will - /// be used. - /// - Replace = 0, - - /// - /// Ignore the new value when there is a duplicate property. The value of the first property in the JSON object will be - /// used. - /// - Ignore = 1, - - /// - /// Throw a when a duplicate property is encountered. - /// - Error = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/Extensions.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/Extensions.cs deleted file mode 100644 index bd0e157ac..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/Extensions.cs +++ /dev/null @@ -1,317 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Contains the LINQ to JSON extension methods. - /// - internal static class Extensions - { - /// - /// Returns a collection of tokens that contains the ancestors of every token in the source collection. - /// - /// The type of the objects in source, constrained to . - /// An of that contains the source collection. - /// - /// An of that contains the ancestors of every token in the - /// source collection. - /// - public static IJEnumerable Ancestors(this IEnumerable source) where T : JToken - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(j => j.Ancestors()).AsJEnumerable(); - } - - /// - /// Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in - /// the source collection. - /// - /// The type of the objects in source, constrained to . - /// An of that contains the source collection. - /// - /// An of that contains every token in the source collection, - /// the ancestors of every token in the source collection. - /// - public static IJEnumerable AncestorsAndSelf(this IEnumerable source) where T : JToken - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(j => j.AncestorsAndSelf()).AsJEnumerable(); - } - - /// - /// Returns a collection of tokens that contains the descendants of every token in the source collection. - /// - /// The type of the objects in source, constrained to . - /// An of that contains the source collection. - /// - /// An of that contains the descendants of every token in the - /// source collection. - /// - public static IJEnumerable Descendants(this IEnumerable source) where T : JContainer - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(j => j.Descendants()).AsJEnumerable(); - } - - /// - /// Returns a collection of tokens that contains every token in the source collection, and the descendants of every token - /// in the source collection. - /// - /// The type of the objects in source, constrained to . - /// An of that contains the source collection. - /// - /// An of that contains every token in the source collection, - /// and the descendants of every token in the source collection. - /// - public static IJEnumerable DescendantsAndSelf(this IEnumerable source) where T : JContainer - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(j => j.DescendantsAndSelf()).AsJEnumerable(); - } - - /// - /// Returns a collection of child properties of every object in the source collection. - /// - /// An of that contains the source collection. - /// - /// An of that contains the properties of every object in - /// the source collection. - /// - public static IJEnumerable Properties(this IEnumerable source) - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(d => d.Properties()).AsJEnumerable(); - } - - /// - /// Returns a collection of child values of every object in the source collection with the given key. - /// - /// An of that contains the source collection. - /// The token key. - /// - /// An of that contains the values of every token in the - /// source collection with the given key. - /// - public static IJEnumerable Values(this IEnumerable source, object? key) => - Values(source, key)!.AsJEnumerable(); - - /// - /// Returns a collection of child values of every object in the source collection. - /// - /// An of that contains the source collection. - /// - /// An of that contains the values of every token in the - /// source collection. - /// - public static IJEnumerable Values(this IEnumerable source) => source.Values(null); - - /// - /// Returns a collection of converted child values of every object in the source collection with the given key. - /// - /// The type to convert the values to. - /// An of that contains the source collection. - /// The token key. - /// - /// An that contains the converted values of every token in the source collection - /// with the given key. - /// - public static IEnumerable Values(this IEnumerable source, object key) => Values(source, key); - - /// - /// Returns a collection of converted child values of every object in the source collection. - /// - /// The type to convert the values to. - /// An of that contains the source collection. - /// An that contains the converted values of every token in the source collection. - public static IEnumerable Values(this IEnumerable source) => Values(source, null); - - /// - /// Converts the value. - /// - /// The type to convert the value to. - /// A cast as a of . - /// A converted value. - public static U? Value(this IEnumerable value) => value.Value(); - - /// - /// Converts the value. - /// - /// The source collection type. - /// The type to convert the value to. - /// A cast as a of . - /// A converted value. - public static U? Value(this IEnumerable value) where T : JToken - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - if (!(value is JToken token)) throw new ArgumentException("Source value must be a JToken."); - - return token.Convert(); - } - - internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - if (key == null) - { - foreach (var token in source) - { - if (token is JValue value) - yield return Convert(value); - else - foreach (var t in token.Children()) - yield return t.Convert(); - } - } - else - { - foreach (var token in source) - { - var value = token[key]; - if (value != null) yield return value.Convert(); - } - } - } - - //TODO - //public static IEnumerable InDocumentOrder(this IEnumerable source) where T : JObject; - - /// - /// Returns a collection of child tokens of every array in the source collection. - /// - /// The source collection type. - /// An of that contains the source collection. - /// - /// An of that contains the values of every token in the - /// source collection. - /// - public static IJEnumerable Children(this IEnumerable source) where T : JToken => Children(source)!.AsJEnumerable(); - - /// - /// Returns a collection of converted child tokens of every array in the source collection. - /// - /// An of that contains the source collection. - /// The type to convert the values to. - /// The source collection type. - /// An that contains the converted values of every token in the source collection. - public static IEnumerable Children(this IEnumerable source) where T : JToken - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - return source.SelectMany(c => c.Children()).Convert(); - } - - internal static IEnumerable Convert(this IEnumerable source) where T : JToken - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - - foreach (var token in source) yield return Convert(token); - } - - internal static U? Convert(this T token) where T : JToken? - { - if (token == null) - { -#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. - return default; -#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. - } - - if (token is U castValue - // don't want to cast JValue to its interfaces, want to get the internal value - && typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable)) - return castValue; - - if (!(token is JValue value)) - throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T))); - - if (value.Value is U u) return u; - - var targetType = typeof(U); - - if (ReflectionUtils.IsNullableType(targetType)) - { - if (value.Value == null) - { -#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. - return default; -#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. - } - - targetType = Nullable.GetUnderlyingType(targetType); - } - - return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture); - } - - //TODO - //public static void Remove(this IEnumerable source) where T : JContainer; - - /// - /// Returns the input typed as . - /// - /// An of that contains the source collection. - /// The input typed as . - public static IJEnumerable AsJEnumerable(this IEnumerable source) => source.AsJEnumerable(); - - /// - /// Returns the input typed as . - /// - /// The source collection type. - /// An of that contains the source collection. - /// The input typed as . - public static IJEnumerable AsJEnumerable(this IEnumerable source) where T : JToken - { - if (source == null) - return null!; - if (source is IJEnumerable customEnumerable) - return customEnumerable; - - return new JEnumerable(source); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/IJEnumerable.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/IJEnumerable.cs deleted file mode 100644 index 61192719e..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/IJEnumerable.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a collection of objects. - /// - /// The type of token. - internal interface IJEnumerable< -#if HAVE_VARIANT_TYPE_PARAMETERS - out -#endif - T> : IEnumerable where T : JToken - { - /// - /// Gets the of with the specified key. - /// - /// - IJEnumerable this[object key] { get; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.Async.cs deleted file mode 100644 index ed13c42d2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.Async.cs +++ /dev/null @@ -1,105 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JArray - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - await writer.WriteStartArrayAsync(cancellationToken).ConfigureAwait(false); - - for (int i = 0; i < _values.Count; i++) - { - await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(false); - } - - await writer.WriteEndArrayAsync(cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// A representing the asynchronous load. The property contains the JSON that was read from the specified . - public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return LoadAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// A representing the asynchronous load. The property contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) - { - if (reader.TokenType == JsonToken.None) - { - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); - } - } - - await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(false); - - if (reader.TokenType != JsonToken.StartArray) - { - throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - JArray a = new JArray(); - a.SetLineInfo(reader as IJsonLineInfo, settings); - - await a.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); - - return a; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.cs deleted file mode 100644 index faf80ff26..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JArray.cs +++ /dev/null @@ -1,344 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a JSON array. - /// - /// - /// - /// - internal partial class JArray : JContainer, IList - { - private readonly List _values = new(); - - /// - /// Initializes a new instance of the class. - /// - public JArray() { } - - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JArray(JArray other) - : base(other) { } - - /// - /// Initializes a new instance of the class with the specified content. - /// - /// The contents of the array. - public JArray(params object[] content) - : this((object)content) { } - - /// - /// Initializes a new instance of the class with the specified content. - /// - /// The contents of the array. - public JArray(object content) => Add(content); - - /// - /// Gets the container's children tokens. - /// - /// The container's children tokens. - protected override IList ChildrenTokens => _values; - - /// - /// Gets a value indicating whether the is read-only. - /// - /// true if the is read-only; otherwise, false. - public bool IsReadOnly => false; - - /// - /// Gets the with the specified key. - /// - /// The with the specified key. - public override JToken? this[object key] - { - get - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is int)) - throw new ArgumentException( - "Accessed JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, - MiscellaneousUtils.ToString(key))); - - return GetItem((int)key); - } - set - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is int)) - throw new ArgumentException( - "Set JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, - MiscellaneousUtils.ToString(key))); - - SetItem((int)key, value); - } - } - - /// - /// Gets or sets the at the specified index. - /// - /// - public JToken this[int index] - { - get => GetItem(index); - set => SetItem(index, value); - } - - /// - /// Gets the node type for this . - /// - /// The type. - public override JTokenType Type => JTokenType.Array; - - internal override bool DeepEquals(JToken node) => node is JArray t && ContentsEqual(t); - - internal override JToken CloneToken() => new JArray(this); - - /// - /// Loads an from a . - /// - /// A that will be read for the content of the . - /// A that contains the JSON that was read from the specified . - public static new JArray Load(JsonReader reader) => Load(reader, null); - - /// - /// Loads an from a . - /// - /// A that will be read for the content of the . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A that contains the JSON that was read from the specified . - public static new JArray Load(JsonReader reader, JsonLoadSettings? settings) - { - if (reader.TokenType == JsonToken.None) - { - if (!reader.Read()) throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); - } - - reader.MoveToContent(); - - if (reader.TokenType != JsonToken.StartArray) - throw JsonReaderException.Create(reader, - "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, - reader.TokenType)); - - var a = new JArray(); - a.SetLineInfo(reader as IJsonLineInfo, settings); - - a.ReadTokenFrom(reader, settings); - - return a; - } - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// A populated from the string that contains JSON. - /// - /// - /// - public static new JArray Parse(string json) => Parse(json, null); - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A populated from the string that contains JSON. - /// - /// - /// - public static new JArray Parse(string json, JsonLoadSettings? settings) - { - using (JsonReader reader = new JsonTextReader(new StringReader(json))) - { - var a = Load(reader, settings); - - while (reader.Read()) - { - // Any content encountered here other than a comment will throw in the reader. - } - - return a; - } - } - - /// - /// Creates a from an object. - /// - /// The object that will be used to create . - /// A with the values of the specified object. - public static new JArray FromObject(object o) => FromObject(o, JsonSerializer.CreateDefault()); - - /// - /// Creates a from an object. - /// - /// The object that will be used to create . - /// The that will be used to read the object. - /// A with the values of the specified object. - public static new JArray FromObject(object o, JsonSerializer jsonSerializer) - { - var token = FromObjectInternal(o, jsonSerializer); - - if (token.Type != JTokenType.Array) - throw new ArgumentException( - "Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - return (JArray)token; - } - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) - { - writer.WriteStartArray(); - - for (var i = 0; i < _values.Count; i++) _values[i].WriteTo(writer, converters); - - writer.WriteEndArray(); - } - - internal override int IndexOfItem(JToken? item) - { - if (item == null) return -1; - - return _values.IndexOfReference(item); - } - - internal override void MergeItem(object content, JsonMergeSettings? settings) - { - var a = IsMultiContent(content) || content is JArray - ? (IEnumerable)content - : null; - if (a == null) return; - - MergeEnumerableContent(this, a, settings); - } - - /// - /// Determines the index of a specific item in the . - /// - /// The object to locate in the . - /// - /// The index of if found in the list; otherwise, -1. - /// - public int IndexOf(JToken item) => IndexOfItem(item); - - /// - /// Inserts an item to the at the specified index. - /// - /// The zero-based index at which should be inserted. - /// The object to insert into the . - /// - /// is not a valid index in the . - /// - public void Insert(int index, JToken item) => InsertItem(index, item, false); - - /// - /// Removes the item at the specified index. - /// - /// The zero-based index of the item to remove. - /// - /// is not a valid index in the . - /// - public void RemoveAt(int index) => RemoveItemAt(index); - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A of that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() => Children().GetEnumerator(); - - /// - /// Adds an item to the . - /// - /// The object to add to the . - public void Add(JToken item) => Add((object)item); - - /// - /// Removes all items from the . - /// - public void Clear() => ClearItems(); - - /// - /// Determines whether the contains a specific value. - /// - /// The object to locate in the . - /// - /// true if is found in the ; otherwise, false. - /// - public bool Contains(JToken item) => ContainsItem(item); - - /// - /// Copies the elements of the to an array, starting at a particular array index. - /// - /// The array. - /// Index of the array. - public void CopyTo(JToken[] array, int arrayIndex) => CopyItemsTo(array, arrayIndex); - - /// - /// Removes the first occurrence of a specific object from the . - /// - /// The object to remove from the . - /// - /// true if was successfully removed from the ; otherwise, - /// false. This method also returns false if is not found in the original - /// . - /// - public bool Remove(JToken item) => RemoveItem(item); - - internal override int GetDeepHashCode() => ContentsHashCode(); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.Async.cs deleted file mode 100644 index 9736bdde4..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.Async.cs +++ /dev/null @@ -1,109 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JConstructor - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - await writer.WriteStartConstructorAsync(Name ?? string.Empty, cancellationToken).ConfigureAwait(false); - - for (int i = 0; i < _values.Count; i++) - { - await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(false); - } - - await writer.WriteEndConstructorAsync(cancellationToken).ConfigureAwait(false); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous load. The - /// property returns a that contains the JSON that was read from the specified . - public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return LoadAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous load. The - /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = - default) - { - if (reader.TokenType == JsonToken.None) - { - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); - } - } - - await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(false); - - if (reader.TokenType != JsonToken.StartConstructor) - { - throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - JConstructor c = new JConstructor((string)reader.Value!); - c.SetLineInfo(reader as IJsonLineInfo, settings); - - await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); - - return c; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.cs deleted file mode 100644 index a353ea42f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JConstructor.cs +++ /dev/null @@ -1,214 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a JSON constructor. - /// - internal partial class JConstructor : JContainer - { - private readonly List _values = new(); - - /// - /// Initializes a new instance of the class. - /// - public JConstructor() { } - - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JConstructor(JConstructor other) - : base(other) => - Name = other.Name; - - /// - /// Initializes a new instance of the class with the specified name and content. - /// - /// The constructor name. - /// The contents of the constructor. - public JConstructor(string name, params object[] content) - : this(name, (object)content) { } - - /// - /// Initializes a new instance of the class with the specified name and content. - /// - /// The constructor name. - /// The contents of the constructor. - public JConstructor(string name, object content) - : this(name) => - Add(content); - - /// - /// Initializes a new instance of the class with the specified name. - /// - /// The constructor name. - public JConstructor(string name) - { - if (name == null) throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) throw new ArgumentException("Constructor name cannot be empty.", nameof(name)); - - Name = name; - } - - /// - /// Gets the container's children tokens. - /// - /// The container's children tokens. - protected override IList ChildrenTokens => _values; - - /// - /// Gets the with the specified key. - /// - /// The with the specified key. - public override JToken? this[object key] - { - get - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is int i)) - throw new ArgumentException( - "Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith( - CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); - - return GetItem(i); - } - set - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is int i)) - throw new ArgumentException( - "Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith( - CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); - - SetItem(i, value); - } - } - - /// - /// Gets or sets the name of this constructor. - /// - /// The constructor name. - public string? Name { get; set; } - - /// - /// Gets the node type for this . - /// - /// The type. - public override JTokenType Type => JTokenType.Constructor; - - internal override int IndexOfItem(JToken? item) - { - if (item == null) return -1; - - return _values.IndexOfReference(item); - } - - internal override void MergeItem(object content, JsonMergeSettings? settings) - { - if (!(content is JConstructor c)) return; - - if (c.Name != null) Name = c.Name; - MergeEnumerableContent(this, c, settings); - } - - internal override bool DeepEquals(JToken node) => node is JConstructor c && Name == c.Name && ContentsEqual(c); - - internal override JToken CloneToken() => new JConstructor(this); - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) - { - writer.WriteStartConstructor(Name!); - - var count = _values.Count; - for (var i = 0; i < count; i++) _values[i].WriteTo(writer, converters); - - writer.WriteEndConstructor(); - } - - internal override int GetDeepHashCode() => (Name?.GetHashCode() ?? 0) ^ ContentsHashCode(); - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// - /// A that contains the JSON that was read from the specified - /// . - /// - public static new JConstructor Load(JsonReader reader) => Load(reader, null); - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// - /// A that contains the JSON that was read from the specified - /// . - /// - public static new JConstructor Load(JsonReader reader, JsonLoadSettings? settings) - { - if (reader.TokenType == JsonToken.None) - { - if (!reader.Read()) throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); - } - - reader.MoveToContent(); - - if (reader.TokenType != JsonToken.StartConstructor) - throw JsonReaderException.Create(reader, - "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith( - CultureInfo.InvariantCulture, reader.TokenType)); - - var c = new JConstructor((string)reader.Value!); - c.SetLineInfo(reader as IJsonLineInfo, settings); - - c.ReadTokenFrom(reader, settings); - - return c; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.Async.cs deleted file mode 100644 index cef7eaf7c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.Async.cs +++ /dev/null @@ -1,173 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal abstract partial class JContainer - { - internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings? options, CancellationToken cancellationToken = default) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - int startDepth = reader.Depth; - - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); - } - - await ReadContentFromAsync(reader, options, cancellationToken).ConfigureAwait(false); - - if (reader.Depth > startDepth) - { - throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); - } - } - - private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) - { - IJsonLineInfo? lineInfo = reader as IJsonLineInfo; - - JContainer? parent = this; - - do - { - if (parent is JProperty p && p.Value != null) - { - if (parent == this) - { - return; - } - - parent = parent.Parent; - } - - MiscellaneousUtils.Assert(parent != null); - - switch (reader.TokenType) - { - case JsonToken.None: - // new reader. move to actual content - break; - case JsonToken.StartArray: - JArray a = new JArray(); - a.SetLineInfo(lineInfo, settings); - parent.Add(a); - parent = a; - break; - - case JsonToken.EndArray: - if (parent == this) - { - return; - } - - parent = parent.Parent; - break; - case JsonToken.StartObject: - JObject o = new JObject(); - o.SetLineInfo(lineInfo, settings); - parent.Add(o); - parent = o; - break; - case JsonToken.EndObject: - if (parent == this) - { - return; - } - - parent = parent.Parent; - break; - case JsonToken.StartConstructor: - JConstructor constructor = new JConstructor(reader.Value!.ToString()); - constructor.SetLineInfo(lineInfo, settings); - parent.Add(constructor); - parent = constructor; - break; - case JsonToken.EndConstructor: - if (parent == this) - { - return; - } - - parent = parent.Parent; - break; - case JsonToken.String: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Date: - case JsonToken.Boolean: - case JsonToken.Bytes: - JValue v = new JValue(reader.Value); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.Comment: - if (settings != null && settings.CommentHandling == CommentHandling.Load) - { - v = JValue.CreateComment(reader.Value!.ToString()); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - } - break; - case JsonToken.Null: - v = JValue.CreateNull(); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.Undefined: - v = JValue.CreateUndefined(); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.PropertyName: - JProperty? property = ReadProperty(reader, settings, lineInfo, parent); - if (property != null) - { - parent = property; - } - else - { - await reader.SkipAsync().ConfigureAwait(false); - } - break; - default: - throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.cs deleted file mode 100644 index 1c7651ea9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JContainer.cs +++ /dev/null @@ -1,1023 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Threading; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_INOTIFY_COLLECTION_CHANGED -using System.Collections.Specialized; -#endif -#if !HAVE_LINQ - -#else -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a token that can contain other tokens. - /// - internal abstract partial class JContainer - : JToken, IList -#if HAVE_COMPONENT_MODEL - , ITypedList, IBindingList -#endif - , IList -#if HAVE_INOTIFY_COLLECTION_CHANGED - , INotifyCollectionChanged -#endif - { -#if HAVE_COMPONENT_MODEL - internal ListChangedEventHandler? _listChanged; - internal AddingNewEventHandler? _addingNew; - - /// - /// Occurs when the list changes or an item in the list changes. - /// - public event ListChangedEventHandler ListChanged - { - add => _listChanged += value; - remove => _listChanged -= value; - } - - /// - /// Occurs before an item is added to the collection. - /// - public event AddingNewEventHandler AddingNew - { - add => _addingNew += value; - remove => _addingNew -= value; - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - internal NotifyCollectionChangedEventHandler? _collectionChanged; - - /// - /// Occurs when the items list of the collection has changed, or the collection is reset. - /// - public event NotifyCollectionChangedEventHandler CollectionChanged - { - add { _collectionChanged += value; } - remove { _collectionChanged -= value; } - } -#endif - - /// - /// Gets the container's children tokens. - /// - /// The container's children tokens. - protected abstract IList ChildrenTokens { get; } - - private object? _syncRoot; -#if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED) - private bool _busy; -#endif - - internal JContainer() { } - - internal JContainer(JContainer other) - : this() - { - ValidationUtils.ArgumentNotNull(other, nameof(other)); - - var i = 0; - foreach (var child in other) - { - TryAddInternal(i, child, false); - i++; - } - - CopyAnnotations(this, other); - } - - internal void CheckReentrancy() - { -#if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED) - if (_busy) - { - throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); - } -#endif - } - - internal virtual IList CreateChildrenCollection() => new List(); - -#if HAVE_COMPONENT_MODEL - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual void OnAddingNew(AddingNewEventArgs e) - { - _addingNew?.Invoke(this, e); - } - - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual void OnListChanged(ListChangedEventArgs e) - { - ListChangedEventHandler? handler = _listChanged; - - if (handler != null) - { - _busy = true; - try - { - handler(this, e); - } - finally - { - _busy = false; - } - } - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) - { - NotifyCollectionChangedEventHandler? handler = _collectionChanged; - - if (handler != null) - { - _busy = true; - try - { - handler(this, e); - } - finally - { - _busy = false; - } - } - } -#endif - - /// - /// Gets a value indicating whether this token has child tokens. - /// - /// - /// true if this token has child values; otherwise, false. - /// - public override bool HasValues => ChildrenTokens.Count > 0; - - internal bool ContentsEqual(JContainer container) - { - if (container == this) return true; - - var t1 = ChildrenTokens; - var t2 = container.ChildrenTokens; - - if (t1.Count != t2.Count) return false; - - for (var i = 0; i < t1.Count; i++) - { - if (!t1[i].DeepEquals(t2[i])) return false; - } - - return true; - } - - /// - /// Get the first child token of this token. - /// - /// - /// A containing the first child token of the . - /// - public override JToken? First - { - get - { - var children = ChildrenTokens; - return children.Count > 0 ? children[0] : null; - } - } - - /// - /// Get the last child token of this token. - /// - /// - /// A containing the last child token of the . - /// - public override JToken? Last - { - get - { - var children = ChildrenTokens; - var count = children.Count; - return count > 0 ? children[count - 1] : null; - } - } - - /// - /// Returns a collection of the child tokens of this token, in document order. - /// - /// - /// An of containing the child tokens of this , in - /// document order. - /// - public override JEnumerable Children() => new(ChildrenTokens); - - /// - /// Returns a collection of the child values of this token, in document order. - /// - /// The type to convert the values to. - /// - /// A containing the child values of this , in document order. - /// - public override IEnumerable Values() where T : default => ChildrenTokens.Convert(); - - /// - /// Returns a collection of the descendant tokens for this token in document order. - /// - /// - /// An of containing the descendant tokens of the - /// . - /// - public IEnumerable Descendants() => GetDescendants(false); - - /// - /// Returns a collection of the tokens that contain this token, and all descendant tokens of this token, in document order. - /// - /// - /// An of containing this token, and all the descendant tokens - /// of the . - /// - public IEnumerable DescendantsAndSelf() => GetDescendants(true); - - internal IEnumerable GetDescendants(bool self) - { - if (self) yield return this; - - foreach (var o in ChildrenTokens) - { - yield return o; - - if (o is JContainer c) - { - foreach (var d in c.Descendants()) yield return d; - } - } - } - - internal bool IsMultiContent([NotNullWhen(true)] object? content) => - content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]); - - internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) - { - if (item == null) return JValue.CreateNull(); - - if (skipParentCheck) return item; - - // to avoid a token having multiple parents or creating a recursive loop, create a copy if... - // the item already has a parent - // the item is being added to itself - // the item is being added to the root parent of itself - if (item.Parent != null || item == this || item.HasValues && Root == item) item = item.CloneToken(); - - return item; - } - - internal abstract int IndexOfItem(JToken? item); - - internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck) - { - var children = ChildrenTokens; - - if (index > children.Count) throw new ArgumentOutOfRangeException(nameof(index), "Index must be within the bounds of the List."); - - CheckReentrancy(); - - item = EnsureParentToken(item, skipParentCheck); - - var previous = index == 0 ? null : children[index - 1]; - // haven't inserted new token yet so next token is still at the inserting index - var next = index == children.Count ? null : children[index]; - - ValidateToken(item, null); - - item.Parent = this; - - item.Previous = previous; - if (previous != null) previous.Next = item; - - item.Next = next; - if (next != null) next.Previous = item; - - children.Insert(index, item); - -#if HAVE_COMPONENT_MODEL - if (_listChanged != null) - { - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - if (_collectionChanged != null) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); - } -#endif - - return true; - } - - internal virtual void RemoveItemAt(int index) - { - var children = ChildrenTokens; - - if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Index is less than 0."); - - if (index >= children.Count) throw new ArgumentOutOfRangeException(nameof(index), "Index is equal to or greater than Count."); - - CheckReentrancy(); - - var item = children[index]; - var previous = index == 0 ? null : children[index - 1]; - var next = index == children.Count - 1 ? null : children[index + 1]; - - if (previous != null) previous.Next = next; - if (next != null) next.Previous = previous; - - item.Parent = null; - item.Previous = null; - item.Next = null; - - children.RemoveAt(index); - -#if HAVE_COMPONENT_MODEL - if (_listChanged != null) - { - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - if (_collectionChanged != null) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); - } -#endif - } - - internal virtual bool RemoveItem(JToken? item) - { - if (item != null) - { - var index = IndexOfItem(item); - if (index >= 0) - { - RemoveItemAt(index); - return true; - } - } - - return false; - } - - internal virtual JToken GetItem(int index) => ChildrenTokens[index]; - - internal virtual void SetItem(int index, JToken? item) - { - var children = ChildrenTokens; - - if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Index is less than 0."); - - if (index >= children.Count) throw new ArgumentOutOfRangeException(nameof(index), "Index is equal to or greater than Count."); - - var existing = children[index]; - - if (IsTokenUnchanged(existing, item)) return; - - CheckReentrancy(); - - item = EnsureParentToken(item, false); - - ValidateToken(item, existing); - - var previous = index == 0 ? null : children[index - 1]; - var next = index == children.Count - 1 ? null : children[index + 1]; - - item.Parent = this; - - item.Previous = previous; - if (previous != null) previous.Next = item; - - item.Next = next; - if (next != null) next.Previous = item; - - children[index] = item; - - existing.Parent = null; - existing.Previous = null; - existing.Next = null; - -#if HAVE_COMPONENT_MODEL - if (_listChanged != null) - { - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - if (_collectionChanged != null) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index)); - } -#endif - } - - internal virtual void ClearItems() - { - CheckReentrancy(); - - var children = ChildrenTokens; - - foreach (var item in children) - { - item.Parent = null; - item.Previous = null; - item.Next = null; - } - - children.Clear(); - -#if HAVE_COMPONENT_MODEL - if (_listChanged != null) - { - OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - if (_collectionChanged != null) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } -#endif - } - - internal virtual void ReplaceItem(JToken existing, JToken replacement) - { - if (existing == null || existing.Parent != this) return; - - var index = IndexOfItem(existing); - SetItem(index, replacement); - } - - internal virtual bool ContainsItem(JToken? item) => IndexOfItem(item) != -1; - - internal virtual void CopyItemsTo(Array array, int arrayIndex) - { - if (array == null) throw new ArgumentNullException(nameof(array)); - - if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex), "arrayIndex is less than 0."); - - if (arrayIndex >= array.Length && arrayIndex != 0) - throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); - - if (Count > array.Length - arrayIndex) - throw new ArgumentException( - "The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); - - var index = 0; - foreach (var token in ChildrenTokens) - { - array.SetValue(token, arrayIndex + index); - index++; - } - } - - internal static bool IsTokenUnchanged(JToken currentValue, JToken? newValue) - { - if (currentValue is JValue v1) - { - if (newValue == null) - { - // null will get turned into a JValue of type null - return v1.Type == JTokenType.Null; - } - - return v1.Equals(newValue); - } - - return false; - } - - internal virtual void ValidateToken(JToken o, JToken? existing) - { - ValidationUtils.ArgumentNotNull(o, nameof(o)); - - if (o.Type == JTokenType.Property) - throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); - } - - /// - /// Adds the specified content as children of this . - /// - /// The content to be added. - public virtual void Add(object? content) => TryAddInternal(ChildrenTokens.Count, content, false); - - internal bool TryAdd(object? content) => TryAddInternal(ChildrenTokens.Count, content, false); - - internal void AddAndSkipParentCheck(JToken token) => TryAddInternal(ChildrenTokens.Count, token, true); - - /// - /// Adds the specified content as the first children of this . - /// - /// The content to be added. - public void AddFirst(object? content) => TryAddInternal(0, content, false); - - internal bool TryAddInternal(int index, object? content, bool skipParentCheck) - { - if (IsMultiContent(content)) - { - var enumerable = (IEnumerable)content; - - var multiIndex = index; - foreach (var c in enumerable) - { - TryAddInternal(multiIndex, c, skipParentCheck); - multiIndex++; - } - - return true; - } - var item = CreateFromContent(content); - - return InsertItem(index, item, skipParentCheck); - } - - internal static JToken CreateFromContent(object? content) - { - if (content is JToken token) return token; - - return new JValue(content); - } - - /// - /// Creates a that can be used to add tokens to the . - /// - /// A that is ready to have content written to it. - public JsonWriter CreateWriter() => new JTokenWriter(this); - - /// - /// Replaces the child nodes of this token with the specified content. - /// - /// The content. - public void ReplaceAll(object content) - { - ClearItems(); - Add(content); - } - - /// - /// Removes the child nodes from this token. - /// - public void RemoveAll() => ClearItems(); - - internal abstract void MergeItem(object content, JsonMergeSettings? settings); - - /// - /// Merge the specified content into this . - /// - /// The content to be merged. - public void Merge(object content) => MergeItem(content, null); - - /// - /// Merge the specified content into this using . - /// - /// The content to be merged. - /// The used to merge the content. - public void Merge(object content, JsonMergeSettings? settings) => MergeItem(content, settings); - - internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) - { - var startDepth = reader.Depth; - - if (!reader.Read()) - throw JsonReaderException.Create(reader, - "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); - - ReadContentFrom(reader, options); - - var endDepth = reader.Depth; - - if (endDepth > startDepth) - throw JsonReaderException.Create(reader, - "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); - } - - internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) - { - ValidationUtils.ArgumentNotNull(r, nameof(r)); - var lineInfo = r as IJsonLineInfo; - - var parent = this; - - do - { - if (parent is JProperty p && p.Value != null) - { - if (parent == this) return; - - parent = parent.Parent; - } - - MiscellaneousUtils.Assert(parent != null); - - switch (r.TokenType) - { - case JsonToken.None: - // new reader. move to actual content - break; - case JsonToken.StartArray: - var a = new JArray(); - a.SetLineInfo(lineInfo, settings); - parent.Add(a); - parent = a; - break; - - case JsonToken.EndArray: - if (parent == this) return; - - parent = parent.Parent; - break; - case JsonToken.StartObject: - var o = new JObject(); - o.SetLineInfo(lineInfo, settings); - parent.Add(o); - parent = o; - break; - case JsonToken.EndObject: - if (parent == this) return; - - parent = parent.Parent; - break; - case JsonToken.StartConstructor: - var constructor = new JConstructor(r.Value!.ToString()); - constructor.SetLineInfo(lineInfo, settings); - parent.Add(constructor); - parent = constructor; - break; - case JsonToken.EndConstructor: - if (parent == this) return; - - parent = parent.Parent; - break; - case JsonToken.String: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Date: - case JsonToken.Boolean: - case JsonToken.Bytes: - var v = new JValue(r.Value); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.Comment: - if (settings != null && settings.CommentHandling == CommentHandling.Load) - { - v = JValue.CreateComment(r.Value!.ToString()); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - } - break; - case JsonToken.Null: - v = JValue.CreateNull(); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.Undefined: - v = JValue.CreateUndefined(); - v.SetLineInfo(lineInfo, settings); - parent.Add(v); - break; - case JsonToken.PropertyName: - var property = ReadProperty(r, settings, lineInfo, parent); - if (property != null) - parent = property; - else - r.Skip(); - break; - default: - throw new InvalidOperationException( - "The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType)); - } - } while (r.Read()); - } - - private static JProperty? ReadProperty(JsonReader r, JsonLoadSettings? settings, IJsonLineInfo? lineInfo, JContainer parent) - { - var duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; - - var parentObject = (JObject)parent; - var propertyName = r.Value!.ToString(); - var existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal); - if (existingPropertyWithName != null) - { - if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore) - return null; - - if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Error) - throw JsonReaderException.Create(r, - "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, - propertyName)); - } - - var property = new JProperty(propertyName); - property.SetLineInfo(lineInfo, settings); - // handle multiple properties with the same name in JSON - if (existingPropertyWithName == null) - parent.Add(property); - else - existingPropertyWithName.Replace(property); - - return property; - } - - internal int ContentsHashCode() - { - var hashCode = 0; - foreach (var item in ChildrenTokens) hashCode ^= item.GetDeepHashCode(); - return hashCode; - } - -#if HAVE_COMPONENT_MODEL - string ITypedList.GetListName(PropertyDescriptor[] listAccessors) - { - return string.Empty; - } - - PropertyDescriptorCollection? ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) - { - ICustomTypeDescriptor? d = First as ICustomTypeDescriptor; - return d?.GetProperties(); - } -#endif - - #region IList Members - - int IList.IndexOf(JToken item) => IndexOfItem(item); - - void IList.Insert(int index, JToken item) => InsertItem(index, item, false); - - void IList.RemoveAt(int index) => RemoveItemAt(index); - - JToken IList.this[int index] - { - get => GetItem(index); - set => SetItem(index, value); - } - - #endregion - - #region ICollection Members - - void ICollection.Add(JToken item) => Add(item); - - void ICollection.Clear() => ClearItems(); - - bool ICollection.Contains(JToken item) => ContainsItem(item); - - void ICollection.CopyTo(JToken[] array, int arrayIndex) => CopyItemsTo(array, arrayIndex); - - bool ICollection.IsReadOnly => false; - - bool ICollection.Remove(JToken item) => RemoveItem(item); - - #endregion - - private JToken? EnsureValue(object value) - { - if (value == null) return null; - - if (value is JToken token) return token; - - throw new ArgumentException("Argument is not a JToken."); - } - - #region IList Members - - int IList.Add(object value) - { - Add(EnsureValue(value)); - return Count - 1; - } - - void IList.Clear() => ClearItems(); - - bool IList.Contains(object value) => ContainsItem(EnsureValue(value)); - - int IList.IndexOf(object value) => IndexOfItem(EnsureValue(value)); - - void IList.Insert(int index, object value) => InsertItem(index, EnsureValue(value), false); - - bool IList.IsFixedSize => false; - - bool IList.IsReadOnly => false; - - void IList.Remove(object value) => RemoveItem(EnsureValue(value)); - - void IList.RemoveAt(int index) => RemoveItemAt(index); - - object IList.this[int index] - { - get => GetItem(index); - set => SetItem(index, EnsureValue(value)); - } - - #endregion - - #region ICollection Members - - void ICollection.CopyTo(Array array, int index) => CopyItemsTo(array, index); - - /// - /// Gets the count of child JSON tokens. - /// - /// The count of child JSON tokens. - public int Count => ChildrenTokens.Count; - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot - { - get - { - if (_syncRoot == null) Interlocked.CompareExchange(ref _syncRoot, new object(), null); - - return _syncRoot; - } - } - - #endregion - - #region IBindingList Members - -#if HAVE_COMPONENT_MODEL - void IBindingList.AddIndex(PropertyDescriptor property) - { - } - - object IBindingList.AddNew() - { - AddingNewEventArgs args = new AddingNewEventArgs(); - OnAddingNew(args); - - if (args.NewObject == null) - { - throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType())); - } - - if (!(args.NewObject is JToken newItem)) - { - throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken))); - } - - Add(newItem); - - return newItem; - } - - bool IBindingList.AllowEdit => true; - - bool IBindingList.AllowNew => true; - - bool IBindingList.AllowRemove => true; - - void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) - { - throw new NotSupportedException(); - } - - int IBindingList.Find(PropertyDescriptor property, object key) - { - throw new NotSupportedException(); - } - - bool IBindingList.IsSorted => false; - - void IBindingList.RemoveIndex(PropertyDescriptor property) - { - } - - void IBindingList.RemoveSort() - { - throw new NotSupportedException(); - } - - ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending; - - PropertyDescriptor? IBindingList.SortProperty => null; - - bool IBindingList.SupportsChangeNotification => true; - - bool IBindingList.SupportsSearching => false; - - bool IBindingList.SupportsSorting => false; -#endif - - #endregion - - internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings? settings) - { - switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) - { - case MergeArrayHandling.Concat: - foreach (JToken item in content) target.Add(item); - break; - case MergeArrayHandling.Union: -#if HAVE_HASH_SET - HashSet items = new HashSet(target, EqualityComparer); - - foreach (JToken item in content) - { - if (items.Add(item)) - { - target.Add(item); - } - } -#else - var items = new Dictionary(EqualityComparer); - foreach (var t in target) items[t] = true; - - foreach (JToken item in content) - { - if (!items.ContainsKey(item)) - { - items[item] = true; - target.Add(item); - } - } -#endif - break; - case MergeArrayHandling.Replace: - if (target == content) break; - - target.ClearItems(); - foreach (JToken item in content) target.Add(item); - break; - case MergeArrayHandling.Merge: - var i = 0; - foreach (var targetItem in content) - { - if (i < target.Count) - { - var sourceItem = target[i]; - - if (sourceItem is JContainer existingContainer) - existingContainer.Merge(targetItem, settings); - else - { - if (targetItem != null) - { - var contentValue = CreateFromContent(targetItem); - if (contentValue.Type != JTokenType.Null) target[i] = contentValue; - } - } - } - else - target.Add(targetItem); - - i++; - } - break; - default: - throw new ArgumentOutOfRangeException(nameof(settings), "Unexpected merge array handling when merging JSON."); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JEnumerable.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JEnumerable.cs deleted file mode 100644 index 10900a3e9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JEnumerable.cs +++ /dev/null @@ -1,125 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a collection of objects. - /// - /// The type of token. - internal readonly struct JEnumerable : IJEnumerable, IEquatable> where T : JToken - { - /// - /// An empty collection of objects. - /// - public static readonly JEnumerable Empty = new(Enumerable.Empty()); - - private readonly IEnumerable _enumerable; - - /// - /// Initializes a new instance of the struct. - /// - /// The enumerable. - public JEnumerable(IEnumerable enumerable) - { - ValidationUtils.ArgumentNotNull(enumerable, nameof(enumerable)); - - _enumerable = enumerable; - } - - /// - /// Returns an enumerator that can be used to iterate through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() => (_enumerable ?? Empty).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Gets the of with the specified key. - /// - /// - public IJEnumerable this[object key] - { - get - { - if (_enumerable == null) return JEnumerable.Empty; - - return new JEnumerable(_enumerable.Values(key)!); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(JEnumerable other) => Equals(_enumerable, other._enumerable); - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (obj is JEnumerable enumerable) return Equals(enumerable); - - return false; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - if (_enumerable == null) return 0; - - return _enumerable.GetHashCode(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.Async.cs deleted file mode 100644 index d450c268e..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.Async.cs +++ /dev/null @@ -1,130 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JObject - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - Task t = writer.WriteStartObjectAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) - { - return AwaitProperties(t, 0, writer, cancellationToken, converters); - } - - for (int i = 0; i < _properties.Count; i++) - { - t = _properties[i].WriteToAsync(writer, cancellationToken, converters); - if (!t.IsCompletedSucessfully()) - { - return AwaitProperties(t, i + 1, writer, cancellationToken, converters); - } - } - - return writer.WriteEndObjectAsync(cancellationToken); - - // Local functions, params renamed (capitalized) so as not to capture and allocate when calling async - async Task AwaitProperties(Task task, int i, JsonWriter Writer, CancellationToken CancellationToken, JsonConverter[] Converters) - { - await task.ConfigureAwait(false); - for (; i < _properties.Count; i++) - { - await _properties[i].WriteToAsync(Writer, CancellationToken, Converters).ConfigureAwait(false); - } - - await Writer.WriteEndObjectAsync(CancellationToken).ConfigureAwait(false); - } - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous load. The - /// property returns a that contains the JSON that was read from the specified . - public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return LoadAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous load. The - /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - if (reader.TokenType == JsonToken.None) - { - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); - } - } - - await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(false); - - if (reader.TokenType != JsonToken.StartObject) - { - throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - JObject o = new JObject(); - o.SetLineInfo(reader as IJsonLineInfo, settings); - - await o.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); - - return o; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.cs deleted file mode 100644 index 700c959d1..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JObject.cs +++ /dev/null @@ -1,752 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_INOTIFY_COLLECTION_CHANGED -using System.Collections.Specialized; -#endif -#if HAVE_DYNAMIC -using System.Dynamic; -using System.Linq.Expressions; -#endif -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a JSON object. - /// - /// - /// - /// - internal partial class JObject : JContainer, IDictionary, INotifyPropertyChanged -#if HAVE_COMPONENT_MODEL - , ICustomTypeDescriptor -#endif -#if HAVE_INOTIFY_PROPERTY_CHANGING - , INotifyPropertyChanging -#endif - { - private readonly JPropertyKeyedCollection _properties = new(); - - /// - /// Gets the container's children tokens. - /// - /// The container's children tokens. - protected override IList ChildrenTokens => _properties; - - /// - /// Occurs when a property value changes. - /// - public event PropertyChangedEventHandler? PropertyChanged; - -#if HAVE_INOTIFY_PROPERTY_CHANGING - /// - /// Occurs when a property value is changing. - /// - public event PropertyChangingEventHandler? PropertyChanging; -#endif - - /// - /// Initializes a new instance of the class. - /// - public JObject() { } - - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JObject(JObject other) - : base(other) { } - - /// - /// Initializes a new instance of the class with the specified content. - /// - /// The contents of the object. - public JObject(params object[] content) - : this((object)content) { } - - /// - /// Initializes a new instance of the class with the specified content. - /// - /// The contents of the object. - public JObject(object content) => Add(content); - - internal override bool DeepEquals(JToken node) - { - if (!(node is JObject t)) return false; - - return _properties.Compare(t._properties); - } - - internal override int IndexOfItem(JToken? item) - { - if (item == null) return -1; - - return _properties.IndexOfReference(item); - } - - internal override bool InsertItem(int index, JToken? item, bool skipParentCheck) - { - // don't add comments to JObject, no name to reference comment by - if (item != null && item.Type == JTokenType.Comment) return false; - - return base.InsertItem(index, item, skipParentCheck); - } - - internal override void ValidateToken(JToken o, JToken? existing) - { - ValidationUtils.ArgumentNotNull(o, nameof(o)); - - if (o.Type != JTokenType.Property) - throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); - - var newProperty = (JProperty)o; - - if (existing != null) - { - var existingProperty = (JProperty)existing; - - if (newProperty.Name == existingProperty.Name) return; - } - - if (_properties.TryGetValue(newProperty.Name, out existing)) - throw new ArgumentException( - "Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, - newProperty.Name, GetType())); - } - - internal override void MergeItem(object content, JsonMergeSettings? settings) - { - if (!(content is JObject o)) return; - - foreach (var contentItem in o) - { - var existingProperty = Property(contentItem.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); - - if (existingProperty == null) - Add(contentItem.Key, contentItem.Value); - else if (contentItem.Value != null) - { - if (!(existingProperty.Value is JContainer existingContainer) || existingContainer.Type != contentItem.Value.Type) - { - if (!IsNull(contentItem.Value) || settings?.MergeNullValueHandling == MergeNullValueHandling.Merge) - existingProperty.Value = contentItem.Value; - } - else - existingContainer.Merge(contentItem.Value, settings); - } - } - } - - private static bool IsNull(JToken token) - { - if (token.Type == JTokenType.Null) return true; - - if (token is JValue v && v.Value == null) return true; - - return false; - } - - internal void InternalPropertyChanged(JProperty childProperty) - { - OnPropertyChanged(childProperty.Name); -#if HAVE_COMPONENT_MODEL - if (_listChanged != null) - { - OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); - } -#endif -#if HAVE_INOTIFY_COLLECTION_CHANGED - if (_collectionChanged != null) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); - } -#endif - } - - internal void InternalPropertyChanging(JProperty childProperty) - { -#if HAVE_INOTIFY_PROPERTY_CHANGING - OnPropertyChanging(childProperty.Name); -#endif - } - - internal override JToken CloneToken() => new JObject(this); - - /// - /// Gets the node type for this . - /// - /// The type. - public override JTokenType Type => JTokenType.Object; - - /// - /// Gets an of of this object's properties. - /// - /// An of of this object's properties. - public IEnumerable Properties() => _properties.Cast(); - - /// - /// Gets a with the specified name. - /// - /// The property name. - /// A with the specified name or null. - public JProperty? Property(string name) => Property(name, StringComparison.Ordinal); - - /// - /// Gets the with the specified name. - /// The exact name will be searched for first and if no matching property is found then - /// the will be used to match a property. - /// - /// The property name. - /// One of the enumeration values that specifies how the strings will be compared. - /// A matched with the specified name or null. - public JProperty? Property(string name, StringComparison comparison) - { - if (name == null) return null; - - if (_properties.TryGetValue(name, out var property)) return (JProperty)property; - - // test above already uses this comparison so no need to repeat - if (comparison != StringComparison.Ordinal) - { - for (var i = 0; i < _properties.Count; i++) - { - var p = (JProperty)_properties[i]; - if (string.Equals(p.Name, name, comparison)) return p; - } - } - - return null; - } - - /// - /// Gets a of of this object's property values. - /// - /// A of of this object's property values. - public JEnumerable PropertyValues() => new(Properties().Select(p => p.Value)); - - /// - /// Gets the with the specified key. - /// - /// The with the specified key. - public override JToken? this[object key] - { - get - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is string propertyName)) - throw new ArgumentException( - "Accessed JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, - MiscellaneousUtils.ToString(key))); - - return this[propertyName]; - } - set - { - ValidationUtils.ArgumentNotNull(key, nameof(key)); - - if (!(key is string propertyName)) - throw new ArgumentException( - "Set JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, - MiscellaneousUtils.ToString(key))); - - this[propertyName] = value; - } - } - - /// - /// Gets or sets the with the specified property name. - /// - /// - public JToken? this[string propertyName] - { - get - { - ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName)); - - var property = Property(propertyName, StringComparison.Ordinal); - - return property?.Value; - } - set - { - var property = Property(propertyName, StringComparison.Ordinal); - if (property != null) - property.Value = value!; - else - { -#if HAVE_INOTIFY_PROPERTY_CHANGING - OnPropertyChanging(propertyName); -#endif - Add(propertyName, value); - OnPropertyChanged(propertyName); - } - } - } - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// A that contains the JSON that was read from the specified . - /// - /// is not valid JSON. - /// - public static new JObject Load(JsonReader reader) => Load(reader, null); - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A that contains the JSON that was read from the specified . - /// - /// is not valid JSON. - /// - public static new JObject Load(JsonReader reader, JsonLoadSettings? settings) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - if (reader.TokenType == JsonToken.None) - if (!reader.Read()) - throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); - - reader.MoveToContent(); - - if (reader.TokenType != JsonToken.StartObject) - throw JsonReaderException.Create(reader, - "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, - reader.TokenType)); - - var o = new JObject(); - o.SetLineInfo(reader as IJsonLineInfo, settings); - - o.ReadTokenFrom(reader, settings); - - return o; - } - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// A populated from the string that contains JSON. - /// - /// is not valid JSON. - /// - /// - /// - /// - public static new JObject Parse(string json) => Parse(json, null); - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A populated from the string that contains JSON. - /// - /// is not valid JSON. - /// - /// - /// - /// - public static new JObject Parse(string json, JsonLoadSettings? settings) - { - using (JsonReader reader = new JsonTextReader(new StringReader(json))) - { - var o = Load(reader, settings); - - while (reader.Read()) - { - // Any content encountered here other than a comment will throw in the reader. - } - - return o; - } - } - - /// - /// Creates a from an object. - /// - /// The object that will be used to create . - /// A with the values of the specified object. - public static new JObject FromObject(object o) => FromObject(o, JsonSerializer.CreateDefault()); - - /// - /// Creates a from an object. - /// - /// The object that will be used to create . - /// The that will be used to read the object. - /// A with the values of the specified object. - public static new JObject FromObject(object o, JsonSerializer jsonSerializer) - { - var token = FromObjectInternal(o, jsonSerializer); - - if (token.Type != JTokenType.Object) - throw new ArgumentException( - "Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - return (JObject)token; - } - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) - { - writer.WriteStartObject(); - - for (var i = 0; i < _properties.Count; i++) _properties[i].WriteTo(writer, converters); - - writer.WriteEndObject(); - } - - /// - /// Gets the with the specified property name. - /// - /// Name of the property. - /// The with the specified property name. - public JToken? GetValue(string? propertyName) => GetValue(propertyName, StringComparison.Ordinal); - - /// - /// Gets the with the specified property name. - /// The exact property name will be searched for first and if no matching property is found then - /// the will be used to match a property. - /// - /// Name of the property. - /// One of the enumeration values that specifies how the strings will be compared. - /// The with the specified property name. - public JToken? GetValue(string? propertyName, StringComparison comparison) - { - if (propertyName == null) return null; - - // attempt to get value via dictionary first for performance - var property = Property(propertyName, comparison); - - return property?.Value; - } - - /// - /// Tries to get the with the specified property name. - /// The exact property name will be searched for first and if no matching property is found then - /// the will be used to match a property. - /// - /// Name of the property. - /// The value. - /// One of the enumeration values that specifies how the strings will be compared. - /// true if a value was successfully retrieved; otherwise, false. - public bool TryGetValue(string propertyName, StringComparison comparison, [NotNullWhen(true)] out JToken? value) - { - value = GetValue(propertyName, comparison); - return value != null; - } - - #region IDictionary Members - - /// - /// Adds the specified property name. - /// - /// Name of the property. - /// The value. - public void Add(string propertyName, JToken? value) => Add(new JProperty(propertyName, value)); - - /// - /// Determines whether the JSON object has the specified property name. - /// - /// Name of the property. - /// true if the JSON object has the specified property name; otherwise, false. - public bool ContainsKey(string propertyName) - { - ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName)); - - return _properties.Contains(propertyName); - } - - ICollection IDictionary.Keys => _properties.Keys; - - /// - /// Removes the property with the specified name. - /// - /// Name of the property. - /// true if item was successfully removed; otherwise, false. - public bool Remove(string propertyName) - { - var property = Property(propertyName, StringComparison.Ordinal); - if (property == null) return false; - - property.Remove(); - return true; - } - - /// - /// Tries to get the with the specified property name. - /// - /// Name of the property. - /// The value. - /// true if a value was successfully retrieved; otherwise, false. - public bool TryGetValue(string propertyName, [NotNullWhen(true)] out JToken? value) - { - var property = Property(propertyName, StringComparison.Ordinal); - if (property == null) - { - value = null; - return false; - } - - value = property.Value; - return true; - } - - ICollection IDictionary.Values => throw new NotImplementedException(); - - #endregion - - #region ICollection> Members - - void ICollection>.Add(KeyValuePair item) => Add(new JProperty(item.Key, item.Value)); - - void ICollection>.Clear() => RemoveAll(); - - bool ICollection>.Contains(KeyValuePair item) - { - var property = Property(item.Key, StringComparison.Ordinal); - if (property == null) return false; - - return property.Value == item.Value; - } - - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (array == null) throw new ArgumentNullException(nameof(array)); - - if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex), "arrayIndex is less than 0."); - - if (arrayIndex >= array.Length && arrayIndex != 0) - throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); - - if (Count > array.Length - arrayIndex) - throw new ArgumentException( - "The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); - - var index = 0; - foreach (JProperty property in _properties) - { - array[arrayIndex + index] = new KeyValuePair(property.Name, property.Value); - index++; - } - } - - bool ICollection>.IsReadOnly => false; - - bool ICollection>.Remove(KeyValuePair item) - { - if (!((ICollection>)this).Contains(item)) return false; - - ((IDictionary)this).Remove(item.Key); - return true; - } - - #endregion - - internal override int GetDeepHashCode() => ContentsHashCode(); - - /// - /// Returns an enumerator that can be used to iterate through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator> GetEnumerator() - { - foreach (JProperty property in _properties) yield return new KeyValuePair(property.Name, property.Value); - } - - /// - /// Raises the event with the provided arguments. - /// - /// Name of the property. - protected virtual void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - -#if HAVE_INOTIFY_PROPERTY_CHANGING - /// - /// Raises the event with the provided arguments. - /// - /// Name of the property. - protected virtual void OnPropertyChanging(string propertyName) - { - PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName)); - } -#endif - -#if HAVE_COMPONENT_MODEL - // include custom type descriptor on JObject rather than use a provider because the properties are specific to a type - - #region ICustomTypeDescriptor - PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() - { - return ((ICustomTypeDescriptor)this).GetProperties(null); - } - - PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) - { - PropertyDescriptor[] propertiesArray = new PropertyDescriptor[Count]; - int i = 0; - foreach (KeyValuePair propertyValue in this) - { - propertiesArray[i] = new JPropertyDescriptor(propertyValue.Key); - i++; - } - - return new PropertyDescriptorCollection(propertiesArray); - } - - AttributeCollection ICustomTypeDescriptor.GetAttributes() - { - return AttributeCollection.Empty; - } - - string? ICustomTypeDescriptor.GetClassName() - { - return null; - } - - string? ICustomTypeDescriptor.GetComponentName() - { - return null; - } - - TypeConverter ICustomTypeDescriptor.GetConverter() - { - return new TypeConverter(); - } - - EventDescriptor? ICustomTypeDescriptor.GetDefaultEvent() - { - return null; - } - - PropertyDescriptor? ICustomTypeDescriptor.GetDefaultProperty() - { - return null; - } - - object? ICustomTypeDescriptor.GetEditor(Type editorBaseType) - { - return null; - } - - EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) - { - return EventDescriptorCollection.Empty; - } - - EventDescriptorCollection ICustomTypeDescriptor.GetEvents() - { - return EventDescriptorCollection.Empty; - } - - object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) - { - if (pd is JPropertyDescriptor) - { - return this; - } - - return null; - } - #endregion - -#endif - -#if HAVE_DYNAMIC - /// - /// Returns the responsible for binding operations performed on this object. - /// - /// The expression tree representation of the runtime value. - /// - /// The to bind this object. - /// - protected override DynamicMetaObject GetMetaObject(Expression parameter) - { - return new DynamicProxyMetaObject(parameter, this, new JObjectDynamicProxy()); - } - - private class JObjectDynamicProxy : DynamicProxy - { - public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object? result) - { - // result can be null - result = instance[binder.Name]; - return true; - } - - public override bool TrySetMember(JObject instance, SetMemberBinder binder, object value) - { - // this can throw an error if value isn't a valid for a JValue - if (!(value is JToken v)) - { - v = new JValue(value); - } - - instance[binder.Name] = v; - return true; - } - - public override IEnumerable GetDynamicMemberNames(JObject instance) - { - return instance.Properties().Select(p => p.Name); - } - } -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.Async.cs deleted file mode 100644 index 2a0e38457..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.Async.cs +++ /dev/null @@ -1,121 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JProperty - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - Task task = writer.WritePropertyNameAsync(Name, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return WriteValueAsync(writer, cancellationToken, converters); - } - - return WriteToAsync(task, writer, cancellationToken, converters); - } - - private async Task WriteToAsync(Task task, JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - await task.ConfigureAwait(false); - - await WriteValueAsync(writer, cancellationToken, converters).ConfigureAwait(false); - } - - private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationToken, JsonConverter[] converters) - { - JToken value = Value; - return value != null - ? value.WriteToAsync(writer, cancellationToken, converters) - : writer.WriteNullAsync(cancellationToken); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The token to monitor for cancellation requests. The default value is . - /// A representing the asynchronous creation. The - /// property returns a that contains the JSON that was read from the specified . - public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return LoadAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously loads a from a . - /// - /// A that will be read for the content of the . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// A representing the asynchronous creation. The - /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = - default) - { - if (reader.TokenType == JsonToken.None) - { - if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); - } - } - - await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(false); - - if (reader.TokenType != JsonToken.PropertyName) - { - throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - - JProperty p = new JProperty((string)reader.Value!); - p.SetLineInfo(reader as IJsonLineInfo, settings); - - await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); - - return p; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.cs deleted file mode 100644 index fdc570db5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JProperty.cs +++ /dev/null @@ -1,310 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a JSON property. - /// - internal partial class JProperty : JContainer - { - private readonly JPropertyList _content = new(); - - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JProperty(JProperty other) - : base(other) => - Name = other.Name; - - internal JProperty(string name) - { - // called from JTokenWriter - ValidationUtils.ArgumentNotNull(name, nameof(name)); - - Name = name; - } - - /// - /// Initializes a new instance of the class. - /// - /// The property name. - /// The property content. - public JProperty(string name, params object[] content) - : this(name, (object)content) { } - - /// - /// Initializes a new instance of the class. - /// - /// The property name. - /// The property content. - public JProperty(string name, object? content) - { - ValidationUtils.ArgumentNotNull(name, nameof(name)); - - Name = name; - - Value = IsMultiContent(content) - ? new JArray(content) - : CreateFromContent(content); - } - - /// - /// Gets the container's children tokens. - /// - /// The container's children tokens. - protected override IList ChildrenTokens => _content; - - /// - /// Gets the property name. - /// - /// The property name. - public string Name { [DebuggerStepThrough] get; } - - /// - /// Gets the node type for this . - /// - /// The type. - public override JTokenType Type - { - [DebuggerStepThrough] - get => JTokenType.Property; - } - - /// - /// Gets or sets the property value. - /// - /// The property value. - public JToken Value - { - [DebuggerStepThrough] - get => _content._token!; - set - { - CheckReentrancy(); - - var newValue = value ?? JValue.CreateNull(); - - if (_content._token == null) - InsertItem(0, newValue, false); - else - SetItem(0, newValue); - } - } - - internal override JToken GetItem(int index) - { - if (index != 0) throw new ArgumentOutOfRangeException(); - - return Value; - } - - internal override void SetItem(int index, JToken? item) - { - if (index != 0) throw new ArgumentOutOfRangeException(); - - if (IsTokenUnchanged(Value, item)) return; - - ((JObject?)Parent)?.InternalPropertyChanging(this); - - base.SetItem(0, item); - - ((JObject?)Parent)?.InternalPropertyChanged(this); - } - - internal override bool RemoveItem(JToken? item) => - throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); - - internal override void RemoveItemAt(int index) => - throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); - - internal override int IndexOfItem(JToken? item) - { - if (item == null) return -1; - - return _content.IndexOf(item); - } - - internal override bool InsertItem(int index, JToken? item, bool skipParentCheck) - { - // don't add comments to JProperty - if (item != null && item.Type == JTokenType.Comment) return false; - - if (Value != null) - throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); - - return base.InsertItem(0, item, false); - } - - internal override bool ContainsItem(JToken? item) => Value == item; - - internal override void MergeItem(object content, JsonMergeSettings? settings) - { - var value = (content as JProperty)?.Value; - - if (value != null && value.Type != JTokenType.Null) Value = value; - } - - internal override void ClearItems() => - throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); - - internal override bool DeepEquals(JToken node) => node is JProperty t && Name == t.Name && ContentsEqual(t); - - internal override JToken CloneToken() => new JProperty(this); - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) - { - writer.WritePropertyName(Name); - - var value = Value; - if (value != null) - value.WriteTo(writer, converters); - else - writer.WriteNull(); - } - - internal override int GetDeepHashCode() => Name.GetHashCode() ^ (Value?.GetDeepHashCode() ?? 0); - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// A that contains the JSON that was read from the specified . - public static new JProperty Load(JsonReader reader) => Load(reader, null); - - /// - /// Loads a from a . - /// - /// A that will be read for the content of the . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A that contains the JSON that was read from the specified . - public static new JProperty Load(JsonReader reader, JsonLoadSettings? settings) - { - if (reader.TokenType == JsonToken.None) - { - if (!reader.Read()) throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); - } - - reader.MoveToContent(); - - if (reader.TokenType != JsonToken.PropertyName) - throw JsonReaderException.Create(reader, - "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, - reader.TokenType)); - - var p = new JProperty((string)reader.Value!); - p.SetLineInfo(reader as IJsonLineInfo, settings); - - p.ReadTokenFrom(reader, settings); - - return p; - } - - private class JPropertyList : IList - { - internal JToken? _token; - - public int Count => _token != null ? 1 : 0; - - public bool IsReadOnly => false; - - public JToken this[int index] - { - get - { - if (index != 0) throw new IndexOutOfRangeException(); - - MiscellaneousUtils.Assert(_token != null); - return _token; - } - set - { - if (index != 0) throw new IndexOutOfRangeException(); - - _token = value; - } - } - - public IEnumerator GetEnumerator() - { - if (_token != null) yield return _token; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public void Add(JToken item) => _token = item; - - public void Clear() => _token = null; - - public bool Contains(JToken item) => _token == item; - - public void CopyTo(JToken[] array, int arrayIndex) - { - if (_token != null) array[arrayIndex] = _token; - } - - public bool Remove(JToken item) - { - if (_token == item) - { - _token = null; - return true; - } - return false; - } - - public int IndexOf(JToken item) => _token == item ? 0 : -1; - - public void Insert(int index, JToken item) - { - if (index == 0) _token = item; - } - - public void RemoveAt(int index) - { - if (index == 0) _token = null; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyDescriptor.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyDescriptor.cs deleted file mode 100644 index a21044d90..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyDescriptor.cs +++ /dev/null @@ -1,159 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_COMPONENT_MODEL -using System; -using System.ComponentModel; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a view of a . - /// - internal class JPropertyDescriptor : PropertyDescriptor - { - /// - /// Initializes a new instance of the class. - /// - /// The name. - public JPropertyDescriptor(string name) - : base(name, null) - { - } - - private static JObject CastInstance(object instance) - { - return (JObject)instance; - } - - /// - /// When overridden in a derived class, returns whether resetting an object changes its value. - /// - /// - /// true if resetting the component changes its value; otherwise, false. - /// - /// The component to test for reset capability. - public override bool CanResetValue(object component) - { - return false; - } - - /// - /// When overridden in a derived class, gets the current value of the property on a component. - /// - /// - /// The value of a property for a given component. - /// - /// The component with the property for which to retrieve the value. - public override object? GetValue(object component) - { - return (component as JObject)?[Name]; - } - - /// - /// When overridden in a derived class, resets the value for this property of the component to the default value. - /// - /// The component with the property value that is to be reset to the default value. - public override void ResetValue(object component) - { - } - - /// - /// When overridden in a derived class, sets the value of the component to a different value. - /// - /// The component with the property value that is to be set. - /// The new value. - public override void SetValue(object component, object value) - { - if (component is JObject o) - { - JToken token = value as JToken ?? new JValue(value); - - o[Name] = token; - } - } - - /// - /// When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted. - /// - /// - /// true if the property should be persisted; otherwise, false. - /// - /// The component with the property to be examined for persistence. - public override bool ShouldSerializeValue(object component) - { - return false; - } - - /// - /// When overridden in a derived class, gets the type of the component this property is bound to. - /// - /// - /// A that represents the type of component this property is bound to. - /// When the or - /// - /// methods are invoked, the object specified might be an instance of this type. - /// - public override Type ComponentType => typeof(JObject); - - /// - /// When overridden in a derived class, gets a value indicating whether this property is read-only. - /// - /// - /// true if the property is read-only; otherwise, false. - /// - public override bool IsReadOnly => false; - - /// - /// When overridden in a derived class, gets the type of the property. - /// - /// - /// A that represents the type of the property. - /// - public override Type PropertyType => typeof(object); - - /// - /// Gets the hash code for the name of the member. - /// - /// - /// - /// The hash code for the name of the member. - /// - protected override int NameHashCode - { - get - { - // override property to fix up an error in its documentation - int nameHashCode = base.NameHashCode; - return nameHashCode; - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs deleted file mode 100644 index c9337ede9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs +++ /dev/null @@ -1,212 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal class JPropertyKeyedCollection : Collection - { - private static readonly IEqualityComparer Comparer = StringComparer.Ordinal; - - public JPropertyKeyedCollection() : base(new List()) { } - - private Dictionary? _dictionary; - - public JToken this[string key] - { - get - { - if (key == null) throw new ArgumentNullException(nameof(key)); - - if (_dictionary != null) return _dictionary[key]; - - throw new KeyNotFoundException(); - } - } - - public ICollection Keys - { - get - { - EnsureDictionary(); - return _dictionary!.Keys; - } - } - - public ICollection Values - { - get - { - EnsureDictionary(); - return _dictionary!.Values; - } - } - - private void AddKey(string key, JToken item) - { - EnsureDictionary(); - _dictionary![key] = item; - } - - protected void ChangeItemKey(JToken item, string newKey) - { - if (!ContainsItem(item)) throw new ArgumentException("The specified item does not exist in this KeyedCollection."); - - var keyForItem = GetKeyForItem(item); - if (!Comparer.Equals(keyForItem, newKey)) - { - if (newKey != null) AddKey(newKey, item); - - if (keyForItem != null) RemoveKey(keyForItem); - } - } - - protected override void ClearItems() - { - base.ClearItems(); - - _dictionary?.Clear(); - } - - public bool Contains(string key) - { - if (key == null) throw new ArgumentNullException(nameof(key)); - - if (_dictionary != null) return _dictionary.ContainsKey(key); - - return false; - } - - private bool ContainsItem(JToken item) - { - if (_dictionary == null) return false; - - var key = GetKeyForItem(item); - return _dictionary.TryGetValue(key, out _); - } - - private void EnsureDictionary() - { - if (_dictionary == null) _dictionary = new Dictionary(Comparer); - } - - private string GetKeyForItem(JToken item) => ((JProperty)item).Name; - - protected override void InsertItem(int index, JToken item) - { - AddKey(GetKeyForItem(item), item); - base.InsertItem(index, item); - } - - public bool Remove(string key) - { - if (key == null) throw new ArgumentNullException(nameof(key)); - - if (_dictionary != null) return _dictionary.TryGetValue(key, out var value) && Remove(value); - - return false; - } - - protected override void RemoveItem(int index) - { - var keyForItem = GetKeyForItem(Items[index]); - RemoveKey(keyForItem); - base.RemoveItem(index); - } - - private void RemoveKey(string key) => _dictionary?.Remove(key); - - protected override void SetItem(int index, JToken item) - { - var keyForItem = GetKeyForItem(item); - var keyAtIndex = GetKeyForItem(Items[index]); - - if (Comparer.Equals(keyAtIndex, keyForItem)) - { - if (_dictionary != null) _dictionary[keyForItem] = item; - } - else - { - AddKey(keyForItem, item); - - if (keyAtIndex != null) RemoveKey(keyAtIndex); - } - base.SetItem(index, item); - } - - public bool TryGetValue(string key, [NotNullWhen(true)] out JToken? value) - { - if (_dictionary == null) - { - value = null; - return false; - } - - return _dictionary.TryGetValue(key, out value); - } - - public int IndexOfReference(JToken t) => ((List)Items).IndexOfReference(t); - - public bool Compare(JPropertyKeyedCollection other) - { - if (this == other) return true; - - // dictionaries in JavaScript aren't ordered - // ignore order when comparing properties - var d1 = _dictionary; - var d2 = other._dictionary; - - if (d1 == null && d2 == null) return true; - - if (d1 == null) return d2!.Count == 0; - - if (d2 == null) return d1.Count == 0; - - if (d1.Count != d2.Count) return false; - - foreach (var keyAndProperty in d1) - { - if (!d2.TryGetValue(keyAndProperty.Key, out var secondValue)) return false; - - var p1 = (JProperty)keyAndProperty.Value; - var p2 = (JProperty)secondValue; - - if (p1.Value == null) return p2.Value == null; - - if (!p1.Value.DeepEquals(p2.Value)) return false; - } - - return true; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.Async.cs deleted file mode 100644 index 51c43617d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.Async.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Globalization; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JRaw - { - /// - /// Asynchronously creates an instance of with the content of the reader's current token. - /// - /// The reader. - /// The token to monitor for cancellation requests. The default value is . - /// A representing the asynchronous creation. The - /// property returns an instance of with the content of the reader's current token. - public static async Task CreateAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) - using (JsonTextWriter jsonWriter = new JsonTextWriter(sw)) - { - await jsonWriter.WriteTokenSyncReadingAsync(reader, cancellationToken).ConfigureAwait(false); - - return new JRaw(sw.ToString()); - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.cs deleted file mode 100644 index 23c1b0dc4..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JRaw.cs +++ /dev/null @@ -1,71 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Globalization; -using System.IO; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a raw JSON string. - /// - internal partial class JRaw : JValue - { - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JRaw(JRaw other) - : base(other) { } - - /// - /// Initializes a new instance of the class. - /// - /// The raw json. - public JRaw(object? rawJson) - : base(rawJson, JTokenType.Raw) { } - - /// - /// Creates an instance of with the content of the reader's current token. - /// - /// The reader. - /// An instance of with the content of the reader's current token. - public static JRaw Create(JsonReader reader) - { - using (var sw = new StringWriter(CultureInfo.InvariantCulture)) - using (var jsonWriter = new JsonTextWriter(sw)) - { - jsonWriter.WriteToken(reader); - - return new JRaw(sw.ToString()); - } - } - - internal override JToken CloneToken() => new JRaw(this); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.Async.cs deleted file mode 100644 index 08556ab15..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.Async.cs +++ /dev/null @@ -1,180 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal abstract partial class JToken - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public virtual Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - throw new NotImplementedException(); - } - - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public Task WriteToAsync(JsonWriter writer, params JsonConverter[] converters) - { - return WriteToAsync(writer, default, converters); - } - - /// - /// Asynchronously creates a from a . - /// - /// An positioned at the token to read into this . - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous creation. The - /// property returns a that contains - /// the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static Task ReadFromAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return ReadFromAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously creates a from a . - /// - /// An positioned at the token to read into this . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous creation. The - /// property returns a that contains - /// the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - if (reader.TokenType == JsonToken.None) - { - if (!await (settings != null && settings.CommentHandling == CommentHandling.Ignore ? reader.ReadAndMoveToContentAsync(cancellationToken) : reader.ReadAsync(cancellationToken)).ConfigureAwait(false)) - { - throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); - } - } - - IJsonLineInfo? lineInfo = reader as IJsonLineInfo; - - switch (reader.TokenType) - { - case JsonToken.StartObject: - return await JObject.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(false); - case JsonToken.StartArray: - return await JArray.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(false); - case JsonToken.StartConstructor: - return await JConstructor.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(false); - case JsonToken.PropertyName: - return await JProperty.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(false); - case JsonToken.String: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Date: - case JsonToken.Boolean: - case JsonToken.Bytes: - JValue v = new JValue(reader.Value); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Comment: - v = JValue.CreateComment(reader.Value?.ToString()); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Null: - v = JValue.CreateNull(); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Undefined: - v = JValue.CreateUndefined(); - v.SetLineInfo(lineInfo, settings); - return v; - default: - throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } - - /// - /// Asynchronously creates a from a . - /// - /// A positioned at the token to read into this . - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous creation. The - /// property returns a that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default) - { - return LoadAsync(reader, null, cancellationToken); - } - - /// - /// Asynchronously creates a from a . - /// - /// A positioned at the token to read into this . - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// The token to monitor for cancellation requests. The default value is . - /// - /// A that represents the asynchronous creation. The - /// property returns a that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) - { - return ReadFromAsync(reader, settings, cancellationToken); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.cs deleted file mode 100644 index bf6b370fb..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JToken.cs +++ /dev/null @@ -1,2307 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System.Dynamic; -using System.Linq.Expressions; -#endif -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents an abstract JSON token. - /// - internal abstract partial class JToken : IJEnumerable, IJsonLineInfo -#if HAVE_ICLONEABLE - , ICloneable -#endif -#if HAVE_DYNAMIC - , IDynamicMetaObjectProvider -#endif - { - private static JTokenEqualityComparer? _equalityComparer; - - private object? _annotations; - - private static readonly JTokenType[] BooleanTypes = - { - JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean - }; - - private static readonly JTokenType[] NumberTypes = - { - JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean - }; -#if HAVE_BIG_INTEGER - private static readonly JTokenType[] BigIntegerTypes = - new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes }; -#endif - private static readonly JTokenType[] StringTypes = - { - JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, - JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri - }; - - private static readonly JTokenType[] GuidTypes = { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes }; - private static readonly JTokenType[] TimeSpanTypes = { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan }; - private static readonly JTokenType[] UriTypes = { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri }; - - private static readonly JTokenType[] CharTypes = - { - JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw - }; - - private static readonly JTokenType[] DateTimeTypes = { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; - - private static readonly JTokenType[] BytesTypes = - { - JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer - }; - - /// - /// Gets a comparer that can compare two tokens for value equality. - /// - /// A that can compare two nodes for value equality. - public static JTokenEqualityComparer EqualityComparer - { - get - { - if (_equalityComparer == null) _equalityComparer = new JTokenEqualityComparer(); - - return _equalityComparer; - } - } - - /// - /// Gets or sets the parent. - /// - /// The parent. - public JContainer? Parent { [DebuggerStepThrough] get; internal set; } - - /// - /// Gets the root of this . - /// - /// The root of this . - public JToken Root - { - get - { - var parent = Parent; - if (parent == null) return this; - - while (parent.Parent != null) parent = parent.Parent; - - return parent; - } - } - - internal abstract JToken CloneToken(); - - internal abstract bool DeepEquals(JToken node); - - /// - /// Gets the node type for this . - /// - /// The type. - public abstract JTokenType Type { get; } - - /// - /// Gets a value indicating whether this token has child tokens. - /// - /// - /// true if this token has child values; otherwise, false. - /// - public abstract bool HasValues { get; } - - /// - /// Compares the values of two tokens, including the values of all descendant tokens. - /// - /// The first to compare. - /// The second to compare. - /// true if the tokens are equal; otherwise false. - public static bool DeepEquals(JToken? t1, JToken? t2) => t1 == t2 || t1 != null && t2 != null && t1.DeepEquals(t2); - - /// - /// Gets the next sibling token of this node. - /// - /// The that contains the next sibling token. - public JToken? Next { get; internal set; } - - /// - /// Gets the previous sibling token of this node. - /// - /// The that contains the previous sibling token. - public JToken? Previous { get; internal set; } - - /// - /// Gets the path of the JSON token. - /// - public string Path - { - get - { - if (Parent == null) return string.Empty; - - var positions = new List(); - JToken? previous = null; - for (var current = this; current != null; current = current.Parent) - { - switch (current.Type) - { - case JTokenType.Property: - var property = (JProperty)current; - positions.Add(new JsonPosition(JsonContainerType.Object) { PropertyName = property.Name }); - break; - case JTokenType.Array: - case JTokenType.Constructor: - if (previous != null) - { - var index = ((IList)current).IndexOf(previous); - - positions.Add(new JsonPosition(JsonContainerType.Array) { Position = index }); - } - break; - } - - previous = current; - } - -#if HAVE_FAST_REVERSE - positions.FastReverse(); -#else - positions.Reverse(); -#endif - - return JsonPosition.BuildPath(positions, null); - } - } - - internal JToken() { } - - /// - /// Adds the specified content immediately after this token. - /// - /// - /// A content object that contains simple content or a collection of content objects to be added - /// after this token. - /// - public void AddAfterSelf(object? content) - { - if (Parent == null) throw new InvalidOperationException("The parent is missing."); - - var index = Parent.IndexOfItem(this); - Parent.TryAddInternal(index + 1, content, false); - } - - /// - /// Adds the specified content immediately before this token. - /// - /// - /// A content object that contains simple content or a collection of content objects to be added - /// before this token. - /// - public void AddBeforeSelf(object? content) - { - if (Parent == null) throw new InvalidOperationException("The parent is missing."); - - var index = Parent.IndexOfItem(this); - Parent.TryAddInternal(index, content, false); - } - - /// - /// Returns a collection of the ancestor tokens of this token. - /// - /// A collection of the ancestor tokens of this token. - public IEnumerable Ancestors() => GetAncestors(false); - - /// - /// Returns a collection of tokens that contain this token, and the ancestors of this token. - /// - /// A collection of tokens that contain this token, and the ancestors of this token. - public IEnumerable AncestorsAndSelf() => GetAncestors(true); - - internal IEnumerable GetAncestors(bool self) - { - for (var current = self ? this : Parent; current != null; current = current.Parent) yield return current; - } - - /// - /// Returns a collection of the sibling tokens after this token, in document order. - /// - /// A collection of the sibling tokens after this tokens, in document order. - public IEnumerable AfterSelf() - { - if (Parent == null) yield break; - - for (var o = Next; o != null; o = o.Next) yield return o; - } - - /// - /// Returns a collection of the sibling tokens before this token, in document order. - /// - /// A collection of the sibling tokens before this token, in document order. - public IEnumerable BeforeSelf() - { - if (Parent == null) yield break; - - for (var o = Parent.First; o != this && o != null; o = o.Next) yield return o; - } - - /// - /// Gets the with the specified key. - /// - /// The with the specified key. - public virtual JToken? this[object key] - { - get => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); - set => throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); - } - - /// - /// Gets the with the specified key converted to the specified type. - /// - /// The type to convert the token to. - /// The token key. - /// The converted token value. - public virtual T? Value(object key) - { - var token = this[key]; - - // null check to fix MonoTouch issue - https://github.com/dolbz/Newtonsoft.Json/commit/a24e3062846b30ee505f3271ac08862bb471b822 - return token == null ? default : token.Convert(); - } - - /// - /// Get the first child token of this token. - /// - /// A containing the first child token of the . - public virtual JToken? First => - throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); - - /// - /// Get the last child token of this token. - /// - /// A containing the last child token of the . - public virtual JToken? Last => - throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); - - /// - /// Returns a collection of the child tokens of this token, in document order. - /// - /// - /// An of containing the child tokens of this - /// , in document order. - /// - public virtual JEnumerable Children() => JEnumerable.Empty; - - /// - /// Returns a collection of the child tokens of this token, in document order, filtered by the specified type. - /// - /// The type to filter the child tokens on. - /// A containing the child tokens of this , in document order. - public JEnumerable Children() where T : JToken => new(Children().OfType()); - - /// - /// Returns a collection of the child values of this token, in document order. - /// - /// The type to convert the values to. - /// A containing the child values of this , in document order. - public virtual IEnumerable Values() => - throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); - - /// - /// Removes this token from its parent. - /// - public void Remove() - { - if (Parent == null) throw new InvalidOperationException("The parent is missing."); - - Parent.RemoveItem(this); - } - - /// - /// Replaces this token with the specified token. - /// - /// The value. - public void Replace(JToken value) - { - if (Parent == null) throw new InvalidOperationException("The parent is missing."); - - Parent.ReplaceItem(this, value); - } - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of which will be used when writing the token. - public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters); - - /// - /// Returns the indented JSON for this token. - /// - /// - /// ToString() returns a non-JSON string value for tokens with a type of . - /// If you want the JSON for all token types then you should use . - /// - /// - /// The indented JSON for this token. - /// - public override string ToString() => ToString(Formatting.Indented); - - /// - /// Returns the JSON for this token using the given formatting and converters. - /// - /// Indicates how the output should be formatted. - /// A collection of s which will be used when writing the token. - /// The JSON for this token using the given formatting and converters. - public string ToString(Formatting formatting, params JsonConverter[] converters) - { - using (var sw = new StringWriter(CultureInfo.InvariantCulture)) - { - var jw = new JsonTextWriter(sw); - jw.Formatting = formatting; - - WriteTo(jw, converters); - - return sw.ToString(); - } - } - - private static JValue? EnsureValue(JToken value) - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - if (value is JProperty property) value = property.Value; - - var v = value as JValue; - - return v; - } - - private static string GetType(JToken token) - { - ValidationUtils.ArgumentNotNull(token, nameof(token)); - - if (token is JProperty p) token = p.Value; - - return token.Type.ToString(); - } - - private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable) => Array.IndexOf(validTypes, o.Type) != -1 - || nullable && (o.Type == JTokenType.Null || o.Type == JTokenType.Undefined); - - #region Cast from operators - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator bool(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, BooleanTypes, false)) - throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return Convert.ToBoolean((int)integer); - } -#endif - - return Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture); - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator DateTimeOffset(JToken value) - { - JValue? v = EnsureValue(value); - if (v == null || !ValidateToken(v, DateTimeTypes, false)) - { - throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - } - - if (v.Value is DateTimeOffset offset) - { - return offset; - } - - if (v.Value is string s) - { - return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture); - } - - return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture)); - } -#endif - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator bool?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, BooleanTypes, true)) - throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return Convert.ToBoolean((int)integer); - } -#endif - - return v.Value != null ? (bool?)Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator long(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (long)integer; - } -#endif - - return Convert.ToInt64(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator DateTime?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, DateTimeTypes, true)) - throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_DATE_TIME_OFFSET - if (v.Value is DateTimeOffset offset) - { - return offset.DateTime; - } -#endif - - return v.Value != null ? (DateTime?)Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture) : null; - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator DateTimeOffset?(JToken? value) - { - if (value == null) - { - return null; - } - - JValue? v = EnsureValue(value); - if (v == null || !ValidateToken(v, DateTimeTypes, true)) - { - throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - } - - if (v.Value == null) - { - return null; - } - if (v.Value is DateTimeOffset offset) - { - return offset; - } - - if (v.Value is string s) - { - return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture); - } - - return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture)); - } -#endif - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator decimal?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (decimal?)integer; - } -#endif - - return v.Value != null ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator double?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (double?)integer; - } -#endif - - return v.Value != null ? (double?)Convert.ToDouble(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator char?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, CharTypes, true)) - throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (char?)integer; - } -#endif - - return v.Value != null ? (char?)Convert.ToChar(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator int(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (int)integer; - } -#endif - - return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator short(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (short)integer; - } -#endif - - return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator ushort(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (ushort)integer; - } -#endif - - return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator char(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, CharTypes, false)) - throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (char)integer; - } -#endif - - return Convert.ToChar(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator byte(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (byte)integer; - } -#endif - - return Convert.ToByte(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator sbyte(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (sbyte)integer; - } -#endif - - return Convert.ToSByte(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator int?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (int?)integer; - } -#endif - - return v.Value != null ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator short?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (short?)integer; - } -#endif - - return v.Value != null ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator ushort?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (ushort?)integer; - } -#endif - - return v.Value != null ? (ushort?)Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator byte?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (byte?)integer; - } -#endif - - return v.Value != null ? (byte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator sbyte?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (sbyte?)integer; - } -#endif - - return v.Value != null ? (sbyte?)Convert.ToSByte(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator DateTime(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, DateTimeTypes, false)) - throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_DATE_TIME_OFFSET - if (v.Value is DateTimeOffset offset) - { - return offset.DateTime; - } -#endif - - return Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator long?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (long?)integer; - } -#endif - - return v.Value != null ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator float?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (float?)integer; - } -#endif - - return v.Value != null ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator decimal(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (decimal)integer; - } -#endif - - return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator uint?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (uint?)integer; - } -#endif - - return v.Value != null ? (uint?)Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator ulong?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, true)) - throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (ulong?)integer; - } -#endif - - return v.Value != null ? (ulong?)Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture) : null; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator double(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (double)integer; - } -#endif - - return Convert.ToDouble(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator float(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (float)integer; - } -#endif - - return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator string?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, StringTypes, true)) - throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value == null) return null; - - if (v.Value is byte[] bytes) return Convert.ToBase64String(bytes); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return integer.ToString(CultureInfo.InvariantCulture); - } -#endif - - return Convert.ToString(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator uint(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (uint)integer; - } -#endif - - return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - - public static explicit operator ulong(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, NumberTypes, false)) - throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return (ulong)integer; - } -#endif - - return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture); - } - - /// - /// Performs an explicit conversion from to []. - /// - /// The value. - /// The result of the conversion. - public static explicit operator byte[]?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, BytesTypes, false)) - throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value is string) return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); -#if HAVE_BIG_INTEGER - if (v.Value is BigInteger integer) - { - return integer.ToByteArray(); - } -#endif - - if (v.Value is byte[] bytes) return bytes; - - throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Guid(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, GuidTypes, false)) - throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value is byte[] bytes) return new Guid(bytes); - - return v.Value is Guid guid ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Guid?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, GuidTypes, true)) - throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value == null) return null; - - if (v.Value is byte[] bytes) return new Guid(bytes); - - return v.Value is Guid guid ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator TimeSpan(JToken value) - { - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, TimeSpanTypes, false)) - throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - return v.Value is TimeSpan span ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - } - - /// - /// Performs an explicit conversion from to of . - /// - /// The value. - /// The result of the conversion. - public static explicit operator TimeSpan?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, TimeSpanTypes, true)) - throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value == null) return null; - - return v.Value is TimeSpan span ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Uri?(JToken? value) - { - if (value == null) return null; - - var v = EnsureValue(value); - if (v == null || !ValidateToken(v, UriTypes, true)) - throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - - if (v.Value == null) return null; - - return v.Value is Uri uri ? uri : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); - } - -#if HAVE_BIG_INTEGER - private static BigInteger ToBigInteger(JToken value) - { - JValue? v = EnsureValue(value); - if (v == null || !ValidateToken(v, BigIntegerTypes, false)) - { - throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - } - - return ConvertUtils.ToBigInteger(v.Value!); - } - - private static BigInteger? ToBigIntegerNullable(JToken value) - { - JValue? v = EnsureValue(value); - if (v == null || !ValidateToken(v, BigIntegerTypes, true)) - { - throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); - } - - if (v.Value == null) - { - return null; - } - - return ConvertUtils.ToBigInteger(v.Value); - } -#endif - - #endregion - - #region Cast to operators - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(bool value) => new JValue(value); - -#if HAVE_DATE_TIME_OFFSET - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(DateTimeOffset value) - { - return new JValue(value); - } -#endif - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(byte value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(byte? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(sbyte value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(sbyte? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(bool? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(long value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(DateTime? value) => new JValue(value); - -#if HAVE_DATE_TIME_OFFSET - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(DateTimeOffset? value) - { - return new JValue(value); - } -#endif - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(decimal? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(double? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(short value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(ushort value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(int value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(int? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(DateTime value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(long? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(float? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(decimal value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(short? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(ushort? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(uint? value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(ulong? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(double value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(float value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(string? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(uint value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - - public static implicit operator JToken(ulong value) => new JValue(value); - - /// - /// Performs an implicit conversion from [] to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(byte[] value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(Uri? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(TimeSpan value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(TimeSpan? value) => new JValue(value); - - /// - /// Performs an implicit conversion from to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(Guid value) => new JValue(value); - - /// - /// Performs an implicit conversion from of to . - /// - /// The value to create a from. - /// The initialized with the specified value. - public static implicit operator JToken(Guid? value) => new JValue(value); - - #endregion - - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => Children().GetEnumerator(); - - internal abstract int GetDeepHashCode(); - - IJEnumerable IJEnumerable.this[object key] => this[key]!; - - /// - /// Creates a for this token. - /// - /// A that can be used to read this token and its descendants. - public JsonReader CreateReader() => new JTokenReader(this); - - internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer) - { - ValidationUtils.ArgumentNotNull(o, nameof(o)); - ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer)); - - JToken token; - using (var jsonWriter = new JTokenWriter()) - { - jsonSerializer.Serialize(jsonWriter, o); - token = jsonWriter.Token!; - } - - return token; - } - - /// - /// Creates a from an object. - /// - /// The object that will be used to create . - /// A with the value of the specified object. - public static JToken FromObject(object o) => FromObjectInternal(o, JsonSerializer.CreateDefault()); - - /// - /// Creates a from an object using the specified . - /// - /// The object that will be used to create . - /// The that will be used when reading the object. - /// A with the value of the specified object. - public static JToken FromObject(object o, JsonSerializer jsonSerializer) => FromObjectInternal(o, jsonSerializer); - - /// - /// Creates an instance of the specified .NET type from the . - /// - /// The object type that the token will be deserialized to. - /// The new object created from the JSON value. - public T? ToObject() => (T?)ToObject(typeof(T)); - - /// - /// Creates an instance of the specified .NET type from the . - /// - /// The object type that the token will be deserialized to. - /// The new object created from the JSON value. - public object? ToObject(Type objectType) - { - if (JsonConvert.DefaultSettings == null) - { - var typeCode = ConvertUtils.GetTypeCode(objectType, out var isEnum); - - if (isEnum) - { - if (Type == JTokenType.String) - { - try - { - // use serializer so JsonConverter(typeof(StringEnumConverter)) + EnumMemberAttributes are respected - return ToObject(objectType, JsonSerializer.CreateDefault()); - } - catch (Exception ex) - { - var enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType); - throw new ArgumentException( - "Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string?)this, enumType.Name), ex); - } - } - - if (Type == JTokenType.Integer) - { - var enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType); - return Enum.ToObject(enumType, ((JValue)this).Value); - } - } - - switch (typeCode) - { - case PrimitiveTypeCode.BooleanNullable: - return (bool?)this; - case PrimitiveTypeCode.Boolean: - return (bool)this; - case PrimitiveTypeCode.CharNullable: - return (char?)this; - case PrimitiveTypeCode.Char: - return (char)this; - case PrimitiveTypeCode.SByte: - return (sbyte)this; - case PrimitiveTypeCode.SByteNullable: - return (sbyte?)this; - case PrimitiveTypeCode.ByteNullable: - return (byte?)this; - case PrimitiveTypeCode.Byte: - return (byte)this; - case PrimitiveTypeCode.Int16Nullable: - return (short?)this; - case PrimitiveTypeCode.Int16: - return (short)this; - case PrimitiveTypeCode.UInt16Nullable: - return (ushort?)this; - case PrimitiveTypeCode.UInt16: - return (ushort)this; - case PrimitiveTypeCode.Int32Nullable: - return (int?)this; - case PrimitiveTypeCode.Int32: - return (int)this; - case PrimitiveTypeCode.UInt32Nullable: - return (uint?)this; - case PrimitiveTypeCode.UInt32: - return (uint)this; - case PrimitiveTypeCode.Int64Nullable: - return (long?)this; - case PrimitiveTypeCode.Int64: - return (long)this; - case PrimitiveTypeCode.UInt64Nullable: - return (ulong?)this; - case PrimitiveTypeCode.UInt64: - return (ulong)this; - case PrimitiveTypeCode.SingleNullable: - return (float?)this; - case PrimitiveTypeCode.Single: - return (float)this; - case PrimitiveTypeCode.DoubleNullable: - return (double?)this; - case PrimitiveTypeCode.Double: - return (double)this; - case PrimitiveTypeCode.DecimalNullable: - return (decimal?)this; - case PrimitiveTypeCode.Decimal: - return (decimal)this; - case PrimitiveTypeCode.DateTimeNullable: - return (DateTime?)this; - case PrimitiveTypeCode.DateTime: - return (DateTime)this; -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffsetNullable: - return (DateTimeOffset?)this; - case PrimitiveTypeCode.DateTimeOffset: - return (DateTimeOffset)this; -#endif - case PrimitiveTypeCode.String: - return (string?)this; - case PrimitiveTypeCode.GuidNullable: - return (Guid?)this; - case PrimitiveTypeCode.Guid: - return (Guid)this; - case PrimitiveTypeCode.Uri: - return (Uri?)this; - case PrimitiveTypeCode.TimeSpanNullable: - return (TimeSpan?)this; - case PrimitiveTypeCode.TimeSpan: - return (TimeSpan)this; -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigIntegerNullable: - return ToBigIntegerNullable(this); - case PrimitiveTypeCode.BigInteger: - return ToBigInteger(this); -#endif - } - } - - return ToObject(objectType, JsonSerializer.CreateDefault()); - } - - /// - /// Creates an instance of the specified .NET type from the using the specified - /// . - /// - /// The object type that the token will be deserialized to. - /// The that will be used when creating the object. - /// The new object created from the JSON value. - public T? ToObject(JsonSerializer jsonSerializer) => (T?)ToObject(typeof(T), jsonSerializer); - - /// - /// Creates an instance of the specified .NET type from the using the specified - /// . - /// - /// The object type that the token will be deserialized to. - /// The that will be used when creating the object. - /// The new object created from the JSON value. - public object? ToObject(Type objectType, JsonSerializer jsonSerializer) - { - ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer)); - - using (var jsonReader = new JTokenReader(this)) return jsonSerializer.Deserialize(jsonReader, objectType); - } - - /// - /// Creates a from a . - /// - /// A positioned at the token to read into this . - /// - /// A that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static JToken ReadFrom(JsonReader reader) => ReadFrom(reader, null); - - /// - /// Creates a from a . - /// - /// An positioned at the token to read into this . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// - /// A that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static JToken ReadFrom(JsonReader reader, JsonLoadSettings? settings) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - bool hasContent; - if (reader.TokenType == JsonToken.None) - { - hasContent = settings != null && settings.CommentHandling == CommentHandling.Ignore - ? reader.ReadAndMoveToContent() - : reader.Read(); - } - else if (reader.TokenType == JsonToken.Comment && settings?.CommentHandling == CommentHandling.Ignore) - hasContent = reader.ReadAndMoveToContent(); - else - hasContent = true; - - if (!hasContent) throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); - - var lineInfo = reader as IJsonLineInfo; - - switch (reader.TokenType) - { - case JsonToken.StartObject: - return JObject.Load(reader, settings); - case JsonToken.StartArray: - return JArray.Load(reader, settings); - case JsonToken.StartConstructor: - return JConstructor.Load(reader, settings); - case JsonToken.PropertyName: - return JProperty.Load(reader, settings); - case JsonToken.String: - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Date: - case JsonToken.Boolean: - case JsonToken.Bytes: - var v = new JValue(reader.Value); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Comment: - v = JValue.CreateComment(reader.Value!.ToString()); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Null: - v = JValue.CreateNull(); - v.SetLineInfo(lineInfo, settings); - return v; - case JsonToken.Undefined: - v = JValue.CreateUndefined(); - v.SetLineInfo(lineInfo, settings); - return v; - default: - throw JsonReaderException.Create(reader, - "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); - } - } - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// A populated from the string that contains JSON. - public static JToken Parse(string json) => Parse(json, null); - - /// - /// Load a from a string that contains JSON. - /// - /// A that contains JSON. - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// A populated from the string that contains JSON. - public static JToken Parse(string json, JsonLoadSettings? settings) - { - using (JsonReader reader = new JsonTextReader(new StringReader(json))) - { - var t = Load(reader, settings); - - while (reader.Read()) - { - // Any content encountered here other than a comment will throw in the reader. - } - - return t; - } - } - - /// - /// Creates a from a . - /// - /// A positioned at the token to read into this . - /// - /// The used to load the JSON. - /// If this is null, default load settings will be used. - /// - /// - /// A that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static JToken Load(JsonReader reader, JsonLoadSettings? settings) => ReadFrom(reader, settings); - - /// - /// Creates a from a . - /// - /// A positioned at the token to read into this . - /// - /// A that contains the token and its descendant tokens - /// that were read from the reader. The runtime type of the token is determined - /// by the token type of the first token encountered in the reader. - /// - public static JToken Load(JsonReader reader) => Load(reader, null); - - internal void SetLineInfo(IJsonLineInfo? lineInfo, JsonLoadSettings? settings) - { - if (settings != null && settings.LineInfoHandling != LineInfoHandling.Load) return; - - if (lineInfo == null || !lineInfo.HasLineInfo()) return; - - SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition); - } - - private class LineInfoAnnotation - { - internal readonly int LineNumber; - internal readonly int LinePosition; - - public LineInfoAnnotation(int lineNumber, int linePosition) - { - LineNumber = lineNumber; - LinePosition = linePosition; - } - } - - internal void SetLineInfo(int lineNumber, int linePosition) => AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition)); - - bool IJsonLineInfo.HasLineInfo() => Annotation() != null; - - int IJsonLineInfo.LineNumber - { - get - { - var annotation = Annotation(); - if (annotation != null) return annotation.LineNumber; - - return 0; - } - } - - int IJsonLineInfo.LinePosition - { - get - { - var annotation = Annotation(); - if (annotation != null) return annotation.LinePosition; - - return 0; - } - } - - /// - /// Selects a using a JSONPath expression. Selects the token that matches the object path. - /// - /// - /// A that contains a JSONPath expression. - /// - /// A , or null. - public JToken? SelectToken(string path) => SelectToken(path, null); - - /// - /// Selects a using a JSONPath expression. Selects the token that matches the object path. - /// - /// - /// A that contains a JSONPath expression. - /// - /// - /// A flag to indicate whether an error should be thrown if no tokens are found when - /// evaluating part of the expression. - /// - /// A . - public JToken? SelectToken(string path, bool errorWhenNoMatch) - { - var settings = errorWhenNoMatch - ? new JsonSelectSettings { ErrorWhenNoMatch = true } - : null; - - return SelectToken(path, settings); - } - - /// - /// Selects a using a JSONPath expression. Selects the token that matches the object path. - /// - /// - /// A that contains a JSONPath expression. - /// - /// The used to select tokens. - /// A . - public JToken? SelectToken(string path, JsonSelectSettings? settings) - { - var p = new JPath(path); - - JToken? token = null; - foreach (var t in p.Evaluate(this, this, settings)) - { - if (token != null) throw new JsonException("Path returned multiple tokens."); - - token = t; - } - - return token; - } - - /// - /// Selects a collection of elements using a JSONPath expression. - /// - /// - /// A that contains a JSONPath expression. - /// - /// An of that contains the selected elements. - public IEnumerable SelectTokens(string path) => SelectTokens(path, null); - - /// - /// Selects a collection of elements using a JSONPath expression. - /// - /// - /// A that contains a JSONPath expression. - /// - /// - /// A flag to indicate whether an error should be thrown if no tokens are found when - /// evaluating part of the expression. - /// - /// An of that contains the selected elements. - public IEnumerable SelectTokens(string path, bool errorWhenNoMatch) - { - var settings = errorWhenNoMatch - ? new JsonSelectSettings { ErrorWhenNoMatch = true } - : null; - - return SelectTokens(path, settings); - } - - /// - /// Selects a collection of elements using a JSONPath expression. - /// - /// - /// A that contains a JSONPath expression. - /// - /// The used to select tokens. - /// An of that contains the selected elements. - public IEnumerable SelectTokens(string path, JsonSelectSettings? settings) - { - var p = new JPath(path); - return p.Evaluate(this, this, settings); - } - -#if HAVE_DYNAMIC - /// - /// Returns the responsible for binding operations performed on this object. - /// - /// The expression tree representation of the runtime value. - /// - /// The to bind this object. - /// - protected virtual DynamicMetaObject GetMetaObject(Expression parameter) - { - return new DynamicProxyMetaObject(parameter, this, new DynamicProxy()); - } - - /// - /// Returns the responsible for binding operations performed on this object. - /// - /// The expression tree representation of the runtime value. - /// - /// The to bind this object. - /// - DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) - { - return GetMetaObject(parameter); - } -#endif - -#if HAVE_ICLONEABLE - object ICloneable.Clone() - { - return DeepClone(); - } -#endif - - /// - /// Creates a new instance of the . All child tokens are recursively cloned. - /// - /// A new instance of the . - public JToken DeepClone() => CloneToken(); - - /// - /// Adds an object to the annotation list of this . - /// - /// The annotation to add. - public void AddAnnotation(object annotation) - { - if (annotation == null) throw new ArgumentNullException(nameof(annotation)); - - if (_annotations == null) - _annotations = annotation is object[] ? new[] { annotation } : annotation; - else - { - if (!(_annotations is object[] annotations)) - _annotations = new[] { _annotations, annotation }; - else - { - var index = 0; - while (index < annotations.Length && annotations[index] != null) index++; - if (index == annotations.Length) - { - Array.Resize(ref annotations, index * 2); - _annotations = annotations; - } - annotations[index] = annotation; - } - } - } - - /// - /// Get the first annotation object of the specified type from this . - /// - /// The type of the annotation to retrieve. - /// - /// The first annotation object that matches the specified type, or null if no annotation is of the - /// specified type. - /// - public T? Annotation() where T : class - { - if (_annotations != null) - { - if (!(_annotations is object[] annotations)) return _annotations as T; - - for (var i = 0; i < annotations.Length; i++) - { - var annotation = annotations[i]; - if (annotation == null) break; - - if (annotation is T local) return local; - } - } - - return default; - } - - /// - /// Gets the first annotation object of the specified type from this . - /// - /// The of the annotation to retrieve. - /// - /// The first annotation object that matches the specified type, or null if no annotation is of the - /// specified type. - /// - public object? Annotation(Type type) - { - if (type == null) throw new ArgumentNullException(nameof(type)); - - if (_annotations != null) - { - if (!(_annotations is object[] annotations)) - { - if (type.IsInstanceOfType(_annotations)) return _annotations; - } - else - { - for (var i = 0; i < annotations.Length; i++) - { - var o = annotations[i]; - if (o == null) break; - - if (type.IsInstanceOfType(o)) return o; - } - } - } - - return null; - } - - /// - /// Gets a collection of annotations of the specified type for this . - /// - /// The type of the annotations to retrieve. - /// An that contains the annotations for this . - public IEnumerable Annotations() where T : class - { - if (_annotations == null) yield break; - - if (_annotations is object[] annotations) - { - for (var i = 0; i < annotations.Length; i++) - { - var o = annotations[i]; - if (o == null) break; - - if (o is T casted) yield return casted; - } - yield break; - } - - if (!(_annotations is T annotation)) yield break; - - yield return annotation; - } - - /// - /// Gets a collection of annotations of the specified type for this . - /// - /// The of the annotations to retrieve. - /// - /// An of that contains the annotations that match the - /// specified type for this . - /// - public IEnumerable Annotations(Type type) - { - if (type == null) throw new ArgumentNullException(nameof(type)); - - if (_annotations == null) yield break; - - if (_annotations is object[] annotations) - { - for (var i = 0; i < annotations.Length; i++) - { - var o = annotations[i]; - if (o == null) break; - - if (type.IsInstanceOfType(o)) yield return o; - } - yield break; - } - - if (!type.IsInstanceOfType(_annotations)) yield break; - - yield return _annotations; - } - - /// - /// Removes the annotations of the specified type from this . - /// - /// The type of annotations to remove. - public void RemoveAnnotations() where T : class - { - if (_annotations != null) - { - if (!(_annotations is object?[] annotations)) - { - if (_annotations is T) _annotations = null; - } - else - { - var index = 0; - var keepCount = 0; - while (index < annotations.Length) - { - var obj2 = annotations[index]; - if (obj2 == null) break; - - if (!(obj2 is T)) annotations[keepCount++] = obj2; - - index++; - } - - if (keepCount != 0) - while (keepCount < index) - annotations[keepCount++] = null; - else - _annotations = null; - } - } - } - - /// - /// Removes the annotations of the specified type from this . - /// - /// The of annotations to remove. - public void RemoveAnnotations(Type type) - { - if (type == null) throw new ArgumentNullException(nameof(type)); - - if (_annotations != null) - { - if (!(_annotations is object?[] annotations)) - { - if (type.IsInstanceOfType(_annotations)) _annotations = null; - } - else - { - var index = 0; - var keepCount = 0; - while (index < annotations.Length) - { - var o = annotations[index]; - if (o == null) break; - - if (!type.IsInstanceOfType(o)) annotations[keepCount++] = o; - - index++; - } - - if (keepCount != 0) - while (keepCount < index) - annotations[keepCount++] = null; - else - _annotations = null; - } - } - } - - internal void CopyAnnotations(JToken target, JToken source) - { - if (source._annotations is object[] annotations) - target._annotations = annotations.ToArray(); - else - target._annotations = source._annotations; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs deleted file mode 100644 index 2d1ee358a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs +++ /dev/null @@ -1,64 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Compares tokens to determine whether they are equal. - /// - internal class JTokenEqualityComparer : IEqualityComparer - { - /// - /// Determines whether the specified objects are equal. - /// - /// The first object of type to compare. - /// The second object of type to compare. - /// - /// true if the specified objects are equal; otherwise, false. - /// - public bool Equals(JToken x, JToken y) => JToken.DeepEquals(x, y); - - /// - /// Returns a hash code for the specified object. - /// - /// The for which a hash code is to be returned. - /// A hash code for the specified object. - /// - /// The type of is a reference type and - /// is null. - /// - public int GetHashCode(JToken obj) - { - if (obj == null) return 0; - - return obj.GetDeepHashCode(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenReader.cs deleted file mode 100644 index 155fcc08f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenReader.cs +++ /dev/null @@ -1,289 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. - /// - internal class JTokenReader : JsonReader, IJsonLineInfo - { - private readonly JToken _root; - - /// - /// Initializes a new instance of the class. - /// - /// The token to read from. - public JTokenReader(JToken token) - { - ValidationUtils.ArgumentNotNull(token, nameof(token)); - - _root = token; - } - - /// - /// Initializes a new instance of the class. - /// - /// The token to read from. - /// The initial path of the token. It is prepended to the returned . - public JTokenReader(JToken token, string initialPath) - : this(token) => - _initialPath = initialPath; - - private string? _initialPath; - private JToken? _parent; - - /// - /// Gets the at the reader's current position. - /// - public JToken? CurrentToken { get; private set; } - - int IJsonLineInfo.LineNumber - { - get - { - if (CurrentState == State.Start) return 0; - - IJsonLineInfo? info = CurrentToken; - if (info != null) return info.LineNumber; - - return 0; - } - } - - int IJsonLineInfo.LinePosition - { - get - { - if (CurrentState == State.Start) return 0; - - IJsonLineInfo? info = CurrentToken; - if (info != null) return info.LinePosition; - - return 0; - } - } - - /// - /// Gets the path of the current JSON token. - /// - public override string Path - { - get - { - var path = base.Path; - - if (_initialPath == null) _initialPath = _root.Path; - - if (!StringUtils.IsNullOrEmpty(_initialPath)) - { - if (StringUtils.IsNullOrEmpty(path)) return _initialPath; - - if (path.StartsWith('[')) - path = _initialPath + path; - else - path = _initialPath + "." + path; - } - - return path; - } - } - - /// - /// Reads the next JSON token from the underlying . - /// - /// - /// true if the next token was read successfully; false if there are no more tokens to read. - /// - public override bool Read() - { - if (CurrentState != State.Start) - { - if (CurrentToken == null) return false; - - if (CurrentToken is JContainer container && _parent != container) - return ReadInto(container); - - return ReadOver(CurrentToken); - } - - // The current value could already be the root value if it is a comment - if (CurrentToken == _root) return false; - - CurrentToken = _root; - SetToken(CurrentToken); - return true; - } - - private bool ReadOver(JToken t) - { - if (t == _root) return ReadToEnd(); - - var next = t.Next; - if (next == null || next == t || t == t.Parent!.Last) - { - if (t.Parent == null) return ReadToEnd(); - - return SetEnd(t.Parent); - } - CurrentToken = next; - SetToken(CurrentToken); - return true; - } - - private bool ReadToEnd() - { - CurrentToken = null; - SetToken(JsonToken.None); - return false; - } - - private JsonToken? GetEndToken(JContainer c) - { - switch (c.Type) - { - case JTokenType.Object: - return JsonToken.EndObject; - case JTokenType.Array: - return JsonToken.EndArray; - case JTokenType.Constructor: - return JsonToken.EndConstructor; - case JTokenType.Property: - return null; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(c.Type), c.Type, "Unexpected JContainer type."); - } - } - - private bool ReadInto(JContainer c) - { - var firstChild = c.First; - if (firstChild == null) - return SetEnd(c); - - SetToken(firstChild); - CurrentToken = firstChild; - _parent = c; - return true; - } - - private bool SetEnd(JContainer c) - { - var endToken = GetEndToken(c); - if (endToken != null) - { - SetToken(endToken.GetValueOrDefault()); - CurrentToken = c; - _parent = c; - return true; - } - return ReadOver(c); - } - - private void SetToken(JToken token) - { - switch (token.Type) - { - case JTokenType.Object: - SetToken(JsonToken.StartObject); - break; - case JTokenType.Array: - SetToken(JsonToken.StartArray); - break; - case JTokenType.Constructor: - SetToken(JsonToken.StartConstructor, ((JConstructor)token).Name); - break; - case JTokenType.Property: - SetToken(JsonToken.PropertyName, ((JProperty)token).Name); - break; - case JTokenType.Comment: - SetToken(JsonToken.Comment, ((JValue)token).Value); - break; - case JTokenType.Integer: - SetToken(JsonToken.Integer, ((JValue)token).Value); - break; - case JTokenType.Float: - SetToken(JsonToken.Float, ((JValue)token).Value); - break; - case JTokenType.String: - SetToken(JsonToken.String, ((JValue)token).Value); - break; - case JTokenType.Boolean: - SetToken(JsonToken.Boolean, ((JValue)token).Value); - break; - case JTokenType.Null: - SetToken(JsonToken.Null, ((JValue)token).Value); - break; - case JTokenType.Undefined: - SetToken(JsonToken.Undefined, ((JValue)token).Value); - break; - case JTokenType.Date: - { - var v = ((JValue)token).Value; - if (v is DateTime dt) v = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); - - SetToken(JsonToken.Date, v); - break; - } - case JTokenType.Raw: - SetToken(JsonToken.Raw, ((JValue)token).Value); - break; - case JTokenType.Bytes: - SetToken(JsonToken.Bytes, ((JValue)token).Value); - break; - case JTokenType.Guid: - SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); - break; - case JTokenType.Uri: - { - var v = ((JValue)token).Value; - SetToken(JsonToken.String, v is Uri uri ? uri.OriginalString : SafeToString(v)); - break; - } - case JTokenType.TimeSpan: - SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); - break; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token.Type), token.Type, "Unexpected JTokenType."); - } - } - - private string? SafeToString(object? value) => value?.ToString(); - - bool IJsonLineInfo.HasLineInfo() - { - if (CurrentState == State.Start) return false; - - IJsonLineInfo? info = CurrentToken; - return info != null && info.HasLineInfo(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenType.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenType.cs deleted file mode 100644 index 6dc75f58b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenType.cs +++ /dev/null @@ -1,126 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies the type of token. - /// - internal enum JTokenType - { - /// - /// No token type has been set. - /// - None = 0, - - /// - /// A JSON object. - /// - Object = 1, - - /// - /// A JSON array. - /// - Array = 2, - - /// - /// A JSON constructor. - /// - Constructor = 3, - - /// - /// A JSON object property. - /// - Property = 4, - - /// - /// A comment. - /// - Comment = 5, - - /// - /// An integer value. - /// - Integer = 6, - - /// - /// A float value. - /// - Float = 7, - - /// - /// A string value. - /// - String = 8, - - /// - /// A boolean value. - /// - Boolean = 9, - - /// - /// A null value. - /// - Null = 10, - - /// - /// An undefined value. - /// - Undefined = 11, - - /// - /// A date value. - /// - Date = 12, - - /// - /// A raw JSON value. - /// - Raw = 13, - - /// - /// A collection of bytes value. - /// - Bytes = 14, - - /// - /// A Guid value. - /// - Guid = 15, - - /// - /// A Uri value. - /// - Uri = 16, - - /// - /// A TimeSpan value. - /// - TimeSpan = 17 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.Async.cs deleted file mode 100644 index b5dce00b1..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.Async.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JTokenWriter - { - // This is the only method that can benefit from Task-based asynchronicity, and that only when - // the reader provides it. - internal override Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) - { - // Since JTokenReader is a common target (and with an optimised path) and since it can't - // read truly async, catch that case. - if (reader is JTokenReader) - { - WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); - return AsyncUtils.CompletedTask; - } - - return WriteTokenSyncReadingAsync(reader, cancellationToken); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.cs deleted file mode 100644 index 6303ce249..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JTokenWriter.cs +++ /dev/null @@ -1,513 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. - /// - internal partial class JTokenWriter : JsonWriter - { - private JContainer? _token; - - private JContainer? _parent; - - // used when writer is writing single value and the value has no containing parent - private JValue? _value; - - /// - /// Gets the at the writer's current position. - /// - public JToken? CurrentToken { get; private set; } - - /// - /// Gets the token being written. - /// - /// The token being written. - public JToken? Token - { - get - { - if (_token != null) return _token; - - return _value; - } - } - - /// - /// Initializes a new instance of the class writing to the given . - /// - /// The container being written to. - public JTokenWriter(JContainer container) - { - ValidationUtils.ArgumentNotNull(container, nameof(container)); - - _token = container; - _parent = container; - } - - /// - /// Initializes a new instance of the class. - /// - public JTokenWriter() { } - - /// - /// Flushes whatever is in the buffer to the underlying . - /// - public override void Flush() { } - - /// - /// Closes this writer. - /// If is set to true, the JSON is auto-completed. - /// - /// - /// Setting to true has no additional effect, since the underlying - /// is a type that cannot be closed. - /// - public override void Close() => base.Close(); - - /// - /// Writes the beginning of a JSON object. - /// - public override void WriteStartObject() - { - base.WriteStartObject(); - - AddParent(new JObject()); - } - - private void AddParent(JContainer container) - { - if (_parent == null) - _token = container; - else - _parent.AddAndSkipParentCheck(container); - - _parent = container; - CurrentToken = container; - } - - private void RemoveParent() - { - CurrentToken = _parent; - _parent = _parent!.Parent; - - if (_parent != null && _parent.Type == JTokenType.Property) _parent = _parent.Parent; - } - - /// - /// Writes the beginning of a JSON array. - /// - public override void WriteStartArray() - { - base.WriteStartArray(); - - AddParent(new JArray()); - } - - /// - /// Writes the start of a constructor with the given name. - /// - /// The name of the constructor. - public override void WriteStartConstructor(string name) - { - base.WriteStartConstructor(name); - - AddParent(new JConstructor(name)); - } - - /// - /// Writes the end. - /// - /// The token. - protected override void WriteEnd(JsonToken token) => RemoveParent(); - - /// - /// Writes the property name of a name/value pair on a JSON object. - /// - /// The name of the property. - public override void WritePropertyName(string name) - { - // avoid duplicate property name exception - // last property name wins - (_parent as JObject)?.Remove(name); - - AddParent(new JProperty(name)); - - // don't set state until after in case of an error - // incorrect state will cause issues if writer is disposed when closing open properties - base.WritePropertyName(name); - } - - private void AddValue(object? value, JsonToken token) => AddValue(new JValue(value), token); - - internal void AddValue(JValue? value, JsonToken token) - { - if (_parent != null) - { - // TryAdd will return false if an invalid JToken type is added. - // For example, a JComment can't be added to a JObject. - // If there is an invalid JToken type then skip it. - if (_parent.TryAdd(value)) - { - CurrentToken = _parent.Last; - - if (_parent.Type == JTokenType.Property) _parent = _parent.Parent; - } - } - else - { - _value = value ?? JValue.CreateNull(); - CurrentToken = _value; - } - } - - #region WriteValue methods - - /// - /// Writes a value. - /// An error will be raised if the value cannot be written as a single JSON token. - /// - /// The value to write. - public override void WriteValue(object? value) - { -#if HAVE_BIG_INTEGER - if (value is BigInteger) - { - InternalWriteValue(JsonToken.Integer); - AddValue(value, JsonToken.Integer); - } - else -#endif - { - base.WriteValue(value); - } - } - - /// - /// Writes a null value. - /// - public override void WriteNull() - { - base.WriteNull(); - AddValue(null, JsonToken.Null); - } - - /// - /// Writes an undefined value. - /// - public override void WriteUndefined() - { - base.WriteUndefined(); - AddValue(null, JsonToken.Undefined); - } - - /// - /// Writes raw JSON. - /// - /// The raw JSON to write. - public override void WriteRaw(string? json) - { - base.WriteRaw(json); - AddValue(new JRaw(json), JsonToken.Raw); - } - - /// - /// Writes a comment /*...*/ containing the specified text. - /// - /// Text to place inside the comment. - public override void WriteComment(string? text) - { - base.WriteComment(text); - AddValue(JValue.CreateComment(text), JsonToken.Comment); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(string? value) - { - base.WriteValue(value); - AddValue(value, JsonToken.String); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(int value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(uint value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(long value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ulong value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(float value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Float); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(double value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Float); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(bool value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Boolean); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(short value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(ushort value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(char value) - { - base.WriteValue(value); - string s; -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - s = value.ToString(CultureInfo.InvariantCulture); -#else - s = value.ToString(); -#endif - AddValue(s, JsonToken.String); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(byte value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - - public override void WriteValue(sbyte value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Integer); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(decimal value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Float); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTime value) - { - base.WriteValue(value); - value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); - AddValue(value, JsonToken.Date); - } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(DateTimeOffset value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Date); - } -#endif - - /// - /// Writes a [] value. - /// - /// The [] value to write. - public override void WriteValue(byte[]? value) - { - base.WriteValue(value); - AddValue(value, JsonToken.Bytes); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(TimeSpan value) - { - base.WriteValue(value); - AddValue(value, JsonToken.String); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Guid value) - { - base.WriteValue(value); - AddValue(value, JsonToken.String); - } - - /// - /// Writes a value. - /// - /// The value to write. - public override void WriteValue(Uri? value) - { - base.WriteValue(value); - AddValue(value, JsonToken.String); - } - - #endregion - - internal override void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) - { - // cloning the token rather than reading then writing it doesn't lose some type information, e.g. Guid, byte[], etc - if (reader is JTokenReader tokenReader && writeChildren && writeDateConstructorAsDate && writeComments) - { - if (tokenReader.TokenType == JsonToken.None) - { - if (!tokenReader.Read()) return; - } - - var value = tokenReader.CurrentToken!.CloneToken(); - - if (_parent != null) - { - _parent.Add(value); - CurrentToken = _parent.Last; - - // if the writer was in a property then move out of it and up to its parent object - if (_parent.Type == JTokenType.Property) - { - _parent = _parent.Parent; - InternalWriteValue(JsonToken.Null); - } - } - else - { - CurrentToken = value; - - if (_token == null && _value == null) - { - _token = value as JContainer; - _value = value as JValue; - } - } - - tokenReader.Skip(); - } - else - base.WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.Async.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.Async.cs deleted file mode 100644 index ca626eb3d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.Async.cs +++ /dev/null @@ -1,140 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System; -using System.Globalization; -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System.Threading; -using System.Threading.Tasks; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - internal partial class JValue - { - /// - /// Writes this token to a asynchronously. - /// - /// A into which this method will write. - /// The token to monitor for cancellation requests. - /// A collection of which will be used when writing the token. - /// A that represents the asynchronous write operation. - public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) - { - if (converters != null && converters.Length > 0 && _value != null) - { - JsonConverter? matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); - if (matchingConverter != null && matchingConverter.CanWrite) - { - // TODO: Call WriteJsonAsync when it exists. - matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); - return AsyncUtils.CompletedTask; - } - } - - switch (_valueType) - { - case JTokenType.Comment: - return writer.WriteCommentAsync(_value?.ToString(), cancellationToken); - case JTokenType.Raw: - return writer.WriteRawValueAsync(_value?.ToString(), cancellationToken); - case JTokenType.Null: - return writer.WriteNullAsync(cancellationToken); - case JTokenType.Undefined: - return writer.WriteUndefinedAsync(cancellationToken); - case JTokenType.Integer: - if (_value is int i) - { - return writer.WriteValueAsync(i, cancellationToken); - } - - if (_value is long l) - { - return writer.WriteValueAsync(l, cancellationToken); - } - - if (_value is ulong ul) - { - return writer.WriteValueAsync(ul, cancellationToken); - } - -#if HAVE_BIG_INTEGER - if (_value is BigInteger integer) - { - return writer.WriteValueAsync(integer, cancellationToken); - } -#endif - - return writer.WriteValueAsync(Convert.ToInt64(_value, CultureInfo.InvariantCulture), cancellationToken); - case JTokenType.Float: - if (_value is decimal dec) - { - return writer.WriteValueAsync(dec, cancellationToken); - } - - if (_value is double d) - { - return writer.WriteValueAsync(d, cancellationToken); - } - - if (_value is float f) - { - return writer.WriteValueAsync(f, cancellationToken); - } - - return writer.WriteValueAsync(Convert.ToDouble(_value, CultureInfo.InvariantCulture), cancellationToken); - case JTokenType.String: - return writer.WriteValueAsync(_value?.ToString(), cancellationToken); - case JTokenType.Boolean: - return writer.WriteValueAsync(Convert.ToBoolean(_value, CultureInfo.InvariantCulture), cancellationToken); - case JTokenType.Date: - if (_value is DateTimeOffset offset) - { - return writer.WriteValueAsync(offset, cancellationToken); - } - - return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken); - case JTokenType.Bytes: - return writer.WriteValueAsync((byte[]?)_value, cancellationToken); - case JTokenType.Guid: - return writer.WriteValueAsync(_value != null ? (Guid?)_value : null, cancellationToken); - case JTokenType.TimeSpan: - return writer.WriteValueAsync(_value != null ? (TimeSpan?)_value : null, cancellationToken); - case JTokenType.Uri: - return writer.WriteValueAsync((Uri?)_value, cancellationToken); - } - - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type."); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.cs deleted file mode 100644 index 04e897cf8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JValue.cs +++ /dev/null @@ -1,1048 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#if HAVE_DYNAMIC -using System.Dynamic; -using System.Linq.Expressions; -#endif -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Represents a value in JSON (string, integer, date, etc). - /// - internal partial class JValue : JToken, IEquatable, IFormattable, IComparable, IComparable -#if HAVE_ICONVERTIBLE - , IConvertible -#endif - { - private JTokenType _valueType; - private object? _value; - - internal JValue(object? value, JTokenType type) - { - _value = value; - _valueType = type; - } - - /// - /// Initializes a new instance of the class from another object. - /// - /// A object to copy from. - public JValue(JValue other) - : this(other.Value, other.Type) => - CopyAnnotations(this, other); - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(long value) - : this(value, JTokenType.Integer) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(decimal value) - : this(value, JTokenType.Float) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(char value) - : this(value, JTokenType.String) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - - public JValue(ulong value) - : this(value, JTokenType.Integer) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(double value) - : this(value, JTokenType.Float) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(float value) - : this(value, JTokenType.Float) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(DateTime value) - : this(value, JTokenType.Date) { } - -#if HAVE_DATE_TIME_OFFSET - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(DateTimeOffset value) - : this(value, JTokenType.Date) - { - } -#endif - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(bool value) - : this(value, JTokenType.Boolean) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(string? value) - : this(value, JTokenType.String) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(Guid value) - : this(value, JTokenType.Guid) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(Uri? value) - : this(value, value != null ? JTokenType.Uri : JTokenType.Null) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(TimeSpan value) - : this(value, JTokenType.TimeSpan) { } - - /// - /// Initializes a new instance of the class with the given value. - /// - /// The value. - public JValue(object? value) - : this(value, GetValueType(null, value)) { } - - internal override bool DeepEquals(JToken node) - { - if (!(node is JValue other)) return false; - - if (other == this) return true; - - return ValuesEquals(this, other); - } - - /// - /// Gets a value indicating whether this token has child tokens. - /// - /// - /// true if this token has child values; otherwise, false. - /// - public override bool HasValues => false; - -#if HAVE_BIG_INTEGER - private static int CompareBigInteger(BigInteger i1, object i2) - { - int result = i1.CompareTo(ConvertUtils.ToBigInteger(i2)); - - if (result != 0) - { - return result; - } - - // converting a fractional number to a BigInteger will lose the fraction - // check for fraction if result is two numbers are equal - if (i2 is decimal d1) - { - return (0m).CompareTo(Math.Abs(d1 - Math.Truncate(d1))); - } - else if (i2 is double || i2 is float) - { - double d = Convert.ToDouble(i2, CultureInfo.InvariantCulture); - return (0d).CompareTo(Math.Abs(d - Math.Truncate(d))); - } - - return result; - } -#endif - - internal static int Compare(JTokenType valueType, object? objA, object? objB) - { - if (objA == objB) return 0; - - if (objB == null) return 1; - - if (objA == null) return -1; - - switch (valueType) - { - case JTokenType.Integer: - { -#if HAVE_BIG_INTEGER - if (objA is BigInteger integerA) - { - return CompareBigInteger(integerA, objB); - } - if (objB is BigInteger integerB) - { - return -CompareBigInteger(integerB, objA); - } -#endif - if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) - return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); - if (objA is float || objB is float || objA is double || objB is double) - return CompareFloat(objA, objB); - - return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture)); - } - case JTokenType.Float: - { -#if HAVE_BIG_INTEGER - if (objA is BigInteger integerA) - { - return CompareBigInteger(integerA, objB); - } - if (objB is BigInteger integerB) - { - return -CompareBigInteger(integerB, objA); - } -#endif - if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) - return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); - - return CompareFloat(objA, objB); - } - case JTokenType.Comment: - case JTokenType.String: - case JTokenType.Raw: - var s1 = Convert.ToString(objA, CultureInfo.InvariantCulture); - var s2 = Convert.ToString(objB, CultureInfo.InvariantCulture); - - return string.CompareOrdinal(s1, s2); - case JTokenType.Boolean: - var b1 = Convert.ToBoolean(objA, CultureInfo.InvariantCulture); - var b2 = Convert.ToBoolean(objB, CultureInfo.InvariantCulture); - - return b1.CompareTo(b2); - case JTokenType.Date: -#if HAVE_DATE_TIME_OFFSET - if (objA is DateTime dateA) - { -#else - var dateA = (DateTime)objA; -#endif - DateTime dateB; - -#if HAVE_DATE_TIME_OFFSET - if (objB is DateTimeOffset offsetB) - { - dateB = offsetB.DateTime; - } - else -#endif - { - dateB = Convert.ToDateTime(objB, CultureInfo.InvariantCulture); - } - - return dateA.CompareTo(dateB); -#if HAVE_DATE_TIME_OFFSET - } - else - { - DateTimeOffset offsetA = (DateTimeOffset)objA; - if (!(objB is DateTimeOffset offsetB)) - { - offsetB = new DateTimeOffset(Convert.ToDateTime(objB, CultureInfo.InvariantCulture)); - } - - return offsetA.CompareTo(offsetB); - } -#endif - case JTokenType.Bytes: - if (!(objB is byte[] bytesB)) throw new ArgumentException("Object must be of type byte[]."); - - var bytesA = objA as byte[]; - MiscellaneousUtils.Assert(bytesA != null); - - return MiscellaneousUtils.ByteArrayCompare(bytesA!, bytesB); - case JTokenType.Guid: - if (!(objB is Guid)) throw new ArgumentException("Object must be of type Guid."); - - var guid1 = (Guid)objA; - var guid2 = (Guid)objB; - - return guid1.CompareTo(guid2); - case JTokenType.Uri: - var uri2 = objB as Uri; - if (uri2 == null) throw new ArgumentException("Object must be of type Uri."); - - var uri1 = (Uri)objA; - - return Comparer.Default.Compare(uri1.ToString(), uri2.ToString()); - case JTokenType.TimeSpan: - if (!(objB is TimeSpan)) throw new ArgumentException("Object must be of type TimeSpan."); - - var ts1 = (TimeSpan)objA; - var ts2 = (TimeSpan)objB; - - return ts1.CompareTo(ts2); - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(valueType), valueType, - "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType)); - } - } - - private static int CompareFloat(object objA, object objB) - { - var d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture); - var d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture); - - // take into account possible floating point errors - if (MathUtils.ApproxEquals(d1, d2)) return 0; - - return d1.CompareTo(d2); - } - -#if HAVE_EXPRESSIONS - private static bool Operation(ExpressionType operation, object? objA, object? objB, out object? result) - { - if (objA is string || objB is string) - { - if (operation == ExpressionType.Add || operation == ExpressionType.AddAssign) - { - result = objA?.ToString() + objB?.ToString(); - return true; - } - } - -#if HAVE_BIG_INTEGER - if (objA is BigInteger || objB is BigInteger) - { - if (objA == null || objB == null) - { - result = null; - return true; - } - - // not that this will lose the fraction - // BigInteger doesn't have operators with non-integer types - BigInteger i1 = ConvertUtils.ToBigInteger(objA); - BigInteger i2 = ConvertUtils.ToBigInteger(objB); - - switch (operation) - { - case ExpressionType.Add: - case ExpressionType.AddAssign: - result = i1 + i2; - return true; - case ExpressionType.Subtract: - case ExpressionType.SubtractAssign: - result = i1 - i2; - return true; - case ExpressionType.Multiply: - case ExpressionType.MultiplyAssign: - result = i1 * i2; - return true; - case ExpressionType.Divide: - case ExpressionType.DivideAssign: - result = i1 / i2; - return true; - } - } - else -#endif - if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) - { - if (objA == null || objB == null) - { - result = null; - return true; - } - - decimal d1 = Convert.ToDecimal(objA, CultureInfo.InvariantCulture); - decimal d2 = Convert.ToDecimal(objB, CultureInfo.InvariantCulture); - - switch (operation) - { - case ExpressionType.Add: - case ExpressionType.AddAssign: - result = d1 + d2; - return true; - case ExpressionType.Subtract: - case ExpressionType.SubtractAssign: - result = d1 - d2; - return true; - case ExpressionType.Multiply: - case ExpressionType.MultiplyAssign: - result = d1 * d2; - return true; - case ExpressionType.Divide: - case ExpressionType.DivideAssign: - result = d1 / d2; - return true; - } - } - else if (objA is float || objB is float || objA is double || objB is double) - { - if (objA == null || objB == null) - { - result = null; - return true; - } - - double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture); - double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture); - - switch (operation) - { - case ExpressionType.Add: - case ExpressionType.AddAssign: - result = d1 + d2; - return true; - case ExpressionType.Subtract: - case ExpressionType.SubtractAssign: - result = d1 - d2; - return true; - case ExpressionType.Multiply: - case ExpressionType.MultiplyAssign: - result = d1 * d2; - return true; - case ExpressionType.Divide: - case ExpressionType.DivideAssign: - result = d1 / d2; - return true; - } - } - else if (objA is int || objA is uint || objA is long || objA is short || objA is ushort || objA is sbyte || objA is byte || - objB is int || objB is uint || objB is long || objB is short || objB is ushort || objB is sbyte || objB is byte) - { - if (objA == null || objB == null) - { - result = null; - return true; - } - - long l1 = Convert.ToInt64(objA, CultureInfo.InvariantCulture); - long l2 = Convert.ToInt64(objB, CultureInfo.InvariantCulture); - - switch (operation) - { - case ExpressionType.Add: - case ExpressionType.AddAssign: - result = l1 + l2; - return true; - case ExpressionType.Subtract: - case ExpressionType.SubtractAssign: - result = l1 - l2; - return true; - case ExpressionType.Multiply: - case ExpressionType.MultiplyAssign: - result = l1 * l2; - return true; - case ExpressionType.Divide: - case ExpressionType.DivideAssign: - result = l1 / l2; - return true; - } - } - - result = null; - return false; - } -#endif - - internal override JToken CloneToken() => new JValue(this); - - /// - /// Creates a comment with the given value. - /// - /// The value. - /// A comment with the given value. - public static JValue CreateComment(string? value) => new(value, JTokenType.Comment); - - /// - /// Creates a string with the given value. - /// - /// The value. - /// A string with the given value. - public static JValue CreateString(string? value) => new(value, JTokenType.String); - - /// - /// Creates a null value. - /// - /// A null value. - public static JValue CreateNull() => new(null, JTokenType.Null); - - /// - /// Creates a undefined value. - /// - /// A undefined value. - public static JValue CreateUndefined() => new(null, JTokenType.Undefined); - - private static JTokenType GetValueType(JTokenType? current, object? value) - { - if (value == null) - return JTokenType.Null; -#if HAVE_ADO_NET - else if (value == DBNull.Value) - { - return JTokenType.Null; - } -#endif - - if (value is string) - return GetStringValueType(current); - - if (value is long || value is int || value is short || value is sbyte - || value is ulong || value is uint || value is ushort || value is byte) - return JTokenType.Integer; - - if (value is Enum) - return JTokenType.Integer; -#if HAVE_BIG_INTEGER - else if (value is BigInteger) - { - return JTokenType.Integer; - } -#endif - - if (value is double || value is float || value is decimal) - return JTokenType.Float; - - if (value is DateTime) - return JTokenType.Date; -#if HAVE_DATE_TIME_OFFSET - else if (value is DateTimeOffset) - { - return JTokenType.Date; - } -#endif - - if (value is byte[]) - return JTokenType.Bytes; - - if (value is bool) - return JTokenType.Boolean; - - if (value is Guid) - return JTokenType.Guid; - - if (value is Uri) - return JTokenType.Uri; - if (value is TimeSpan) return JTokenType.TimeSpan; - - throw new ArgumentException( - "Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); - } - - private static JTokenType GetStringValueType(JTokenType? current) - { - if (current == null) return JTokenType.String; - - switch (current.GetValueOrDefault()) - { - case JTokenType.Comment: - case JTokenType.String: - case JTokenType.Raw: - return current.GetValueOrDefault(); - default: - return JTokenType.String; - } - } - - /// - /// Gets the node type for this . - /// - /// The type. - public override JTokenType Type => _valueType; - - /// - /// Gets or sets the underlying token value. - /// - /// The underlying token value. - public object? Value - { - get => _value; - set - { - var currentType = _value?.GetType(); - var newType = value?.GetType(); - - if (currentType != newType) _valueType = GetValueType(_valueType, value); - - _value = value; - } - } - - /// - /// Writes this token to a . - /// - /// A into which this method will write. - /// A collection of s which will be used when writing the token. - public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) - { - if (converters != null && converters.Length > 0 && _value != null) - { - var matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); - if (matchingConverter != null && matchingConverter.CanWrite) - { - matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); - return; - } - } - - switch (_valueType) - { - case JTokenType.Comment: - writer.WriteComment(_value?.ToString()); - return; - case JTokenType.Raw: - writer.WriteRawValue(_value?.ToString()); - return; - case JTokenType.Null: - writer.WriteNull(); - return; - case JTokenType.Undefined: - writer.WriteUndefined(); - return; - case JTokenType.Integer: - if (_value is int i) - writer.WriteValue(i); - else if (_value is long l) - writer.WriteValue(l); - else if (_value is ulong ul) - writer.WriteValue(ul); -#if HAVE_BIG_INTEGER - else if (_value is BigInteger integer) - { - writer.WriteValue(integer); - } -#endif - else - writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); - return; - case JTokenType.Float: - if (_value is decimal dec) - writer.WriteValue(dec); - else if (_value is double d) - writer.WriteValue(d); - else if (_value is float f) - writer.WriteValue(f); - else - writer.WriteValue(Convert.ToDouble(_value, CultureInfo.InvariantCulture)); - return; - case JTokenType.String: - writer.WriteValue(_value?.ToString()); - return; - case JTokenType.Boolean: - writer.WriteValue(Convert.ToBoolean(_value, CultureInfo.InvariantCulture)); - return; - case JTokenType.Date: -#if HAVE_DATE_TIME_OFFSET - if (_value is DateTimeOffset offset) - { - writer.WriteValue(offset); - } - else -#endif - { - writer.WriteValue(Convert.ToDateTime(_value, CultureInfo.InvariantCulture)); - } - return; - case JTokenType.Bytes: - writer.WriteValue((byte[]?)_value); - return; - case JTokenType.Guid: - writer.WriteValue(_value != null ? (Guid?)_value : null); - return; - case JTokenType.TimeSpan: - writer.WriteValue(_value != null ? (TimeSpan?)_value : null); - return; - case JTokenType.Uri: - writer.WriteValue((Uri?)_value); - return; - } - - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type."); - } - - internal override int GetDeepHashCode() - { - var valueHashCode = _value != null ? _value.GetHashCode() : 0; - - // GetHashCode on an enum boxes so cast to int - return ((int)_valueType).GetHashCode() ^ valueHashCode; - } - - private static bool ValuesEquals(JValue v1, JValue v2) => - v1 == v2 || v1._valueType == v2._valueType && Compare(v1._valueType, v1._value, v2._value) == 0; - - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// - /// true if the current object is equal to the parameter; otherwise, false. - /// - /// An object to compare with this object. - public bool Equals(JValue? other) - { - if (other == null) return false; - - return ValuesEquals(this, other); - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// - /// true if the specified is equal to the current ; otherwise, - /// false. - /// - public override bool Equals(object obj) - { - if (obj is JValue v) return Equals(v); - - return false; - } - - /// - /// Serves as a hash function for a particular type. - /// - /// - /// A hash code for the current . - /// - public override int GetHashCode() - { - if (_value == null) return 0; - - return _value.GetHashCode(); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// ToString() returns a non-JSON string value for tokens with a type of . - /// If you want the JSON for all token types then you should use . - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - if (_value == null) return string.Empty; - - return _value.ToString(); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture); - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) => ToString(null, formatProvider); - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string? format, IFormatProvider formatProvider) - { - if (_value == null) return string.Empty; - - if (_value is IFormattable formattable) - return formattable.ToString(format, formatProvider); - - return _value.ToString(); - } - -#if HAVE_DYNAMIC - /// - /// Returns the responsible for binding operations performed on this object. - /// - /// The expression tree representation of the runtime value. - /// - /// The to bind this object. - /// - protected override DynamicMetaObject GetMetaObject(Expression parameter) - { - return new DynamicProxyMetaObject(parameter, this, new JValueDynamicProxy()); - } - - private class JValueDynamicProxy : DynamicProxy - { - public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)]out object? result) - { - if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken)) - { - result = instance; - return true; - } - - object? value = instance.Value; - - if (value == null) - { - result = null; - return ReflectionUtils.IsNullable(binder.Type); - } - - result = ConvertUtils.Convert(value, CultureInfo.InvariantCulture, binder.Type); - return true; - } - - public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, [NotNullWhen(true)]out object? result) - { - object? compareValue = arg is JValue value ? value.Value : arg; - - switch (binder.Operation) - { - case ExpressionType.Equal: - result = (Compare(instance.Type, instance.Value, compareValue) == 0); - return true; - case ExpressionType.NotEqual: - result = (Compare(instance.Type, instance.Value, compareValue) != 0); - return true; - case ExpressionType.GreaterThan: - result = (Compare(instance.Type, instance.Value, compareValue) > 0); - return true; - case ExpressionType.GreaterThanOrEqual: - result = (Compare(instance.Type, instance.Value, compareValue) >= 0); - return true; - case ExpressionType.LessThan: - result = (Compare(instance.Type, instance.Value, compareValue) < 0); - return true; - case ExpressionType.LessThanOrEqual: - result = (Compare(instance.Type, instance.Value, compareValue) <= 0); - return true; - case ExpressionType.Add: - case ExpressionType.AddAssign: - case ExpressionType.Subtract: - case ExpressionType.SubtractAssign: - case ExpressionType.Multiply: - case ExpressionType.MultiplyAssign: - case ExpressionType.Divide: - case ExpressionType.DivideAssign: - if (Operation(binder.Operation, instance.Value, compareValue, out result)) - { - result = new JValue(result); - return true; - } - break; - } - - result = null; - return false; - } - } -#endif - - int IComparable.CompareTo(object obj) - { - if (obj == null) return 1; - - JTokenType comparisonType; - object? otherValue; - if (obj is JValue value) - { - otherValue = value.Value; - comparisonType = _valueType == JTokenType.String && _valueType != value._valueType - ? value._valueType - : _valueType; - } - else - { - otherValue = obj; - comparisonType = _valueType; - } - - return Compare(comparisonType, _value, otherValue); - } - - /// - /// Compares the current instance with another object of the same type and returns an integer that indicates whether the - /// current instance precedes, follows, or occurs in the same position in the sort order as the other object. - /// - /// An object to compare with this instance. - /// - /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these - /// meanings: - /// Value - /// Meaning - /// Less than zero - /// This instance is less than . - /// Zero - /// This instance is equal to . - /// Greater than zero - /// This instance is greater than . - /// - /// - /// is not of the same type as this instance. - /// - public int CompareTo(JValue obj) - { - if (obj == null) return 1; - - var comparisonType = _valueType == JTokenType.String && _valueType != obj._valueType - ? obj._valueType - : _valueType; - - return Compare(comparisonType, _value, obj._value); - } - -#if HAVE_ICONVERTIBLE - TypeCode IConvertible.GetTypeCode() - { - if (_value == null) - { - return TypeCode.Empty; - } - - if (_value is IConvertible convertable) - { - return convertable.GetTypeCode(); - } - - return TypeCode.Object; - } - - bool IConvertible.ToBoolean(IFormatProvider provider) - { - return (bool)this; - } - - char IConvertible.ToChar(IFormatProvider provider) - { - return (char)this; - } - - sbyte IConvertible.ToSByte(IFormatProvider provider) - { - return (sbyte)this; - } - - byte IConvertible.ToByte(IFormatProvider provider) - { - return (byte)this; - } - - short IConvertible.ToInt16(IFormatProvider provider) - { - return (short)this; - } - - ushort IConvertible.ToUInt16(IFormatProvider provider) - { - return (ushort)this; - } - - int IConvertible.ToInt32(IFormatProvider provider) - { - return (int)this; - } - - uint IConvertible.ToUInt32(IFormatProvider provider) - { - return (uint)this; - } - - long IConvertible.ToInt64(IFormatProvider provider) - { - return (long)this; - } - - ulong IConvertible.ToUInt64(IFormatProvider provider) - { - return (ulong)this; - } - - float IConvertible.ToSingle(IFormatProvider provider) - { - return (float)this; - } - - double IConvertible.ToDouble(IFormatProvider provider) - { - return (double)this; - } - - decimal IConvertible.ToDecimal(IFormatProvider provider) - { - return (decimal)this; - } - - DateTime IConvertible.ToDateTime(IFormatProvider provider) - { - return (DateTime)this; - } - - object? IConvertible.ToType(Type conversionType, IFormatProvider provider) - { - return ToObject(conversionType); - } -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonLoadSettings.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonLoadSettings.cs deleted file mode 100644 index a8ffd3038..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonLoadSettings.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies the settings used when loading JSON. - /// - internal class JsonLoadSettings - { - /// - /// Initializes a new instance of the class. - /// - public JsonLoadSettings() - { - _lineInfoHandling = LineInfoHandling.Load; - _commentHandling = CommentHandling.Ignore; - _duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace; - } - - private CommentHandling _commentHandling; - private DuplicatePropertyNameHandling _duplicatePropertyNameHandling; - private LineInfoHandling _lineInfoHandling; - - /// - /// Gets or sets how JSON comments are handled when loading JSON. - /// The default value is . - /// - /// The JSON comment handling. - public CommentHandling CommentHandling - { - get => _commentHandling; - set - { - if (value < CommentHandling.Ignore || value > CommentHandling.Load) throw new ArgumentOutOfRangeException(nameof(value)); - - _commentHandling = value; - } - } - - /// - /// Gets or sets how duplicate property names in JSON objects are handled when loading JSON. - /// The default value is . - /// - /// The JSON duplicate property name handling. - public DuplicatePropertyNameHandling DuplicatePropertyNameHandling - { - get => _duplicatePropertyNameHandling; - set - { - if (value < DuplicatePropertyNameHandling.Replace || value > DuplicatePropertyNameHandling.Error) - throw new ArgumentOutOfRangeException(nameof(value)); - - _duplicatePropertyNameHandling = value; - } - } - - /// - /// Gets or sets how JSON line info is handled when loading JSON. - /// The default value is . - /// - /// The JSON line info handling. - public LineInfoHandling LineInfoHandling - { - get => _lineInfoHandling; - set - { - if (value < LineInfoHandling.Ignore || value > LineInfoHandling.Load) throw new ArgumentOutOfRangeException(nameof(value)); - - _lineInfoHandling = value; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonMergeSettings.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonMergeSettings.cs deleted file mode 100644 index 2d292b96b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonMergeSettings.cs +++ /dev/null @@ -1,96 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies the settings used when merging JSON. - /// - internal class JsonMergeSettings - { - /// - /// Initializes a new instance of the class. - /// - public JsonMergeSettings() => _propertyNameComparison = StringComparison.Ordinal; - - private MergeArrayHandling _mergeArrayHandling; - private MergeNullValueHandling _mergeNullValueHandling; - private StringComparison _propertyNameComparison; - - /// - /// Gets or sets the method used when merging JSON arrays. - /// - /// The method used when merging JSON arrays. - public MergeArrayHandling MergeArrayHandling - { - get => _mergeArrayHandling; - set - { - if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge) throw new ArgumentOutOfRangeException(nameof(value)); - - _mergeArrayHandling = value; - } - } - - /// - /// Gets or sets how null value properties are merged. - /// - /// How null value properties are merged. - public MergeNullValueHandling MergeNullValueHandling - { - get => _mergeNullValueHandling; - set - { - if (value < MergeNullValueHandling.Ignore || value > MergeNullValueHandling.Merge) - throw new ArgumentOutOfRangeException(nameof(value)); - - _mergeNullValueHandling = value; - } - } - - /// - /// Gets or sets the comparison used to match property names while merging. - /// The exact property name will be searched for first and if no matching property is found then - /// the will be used to match a property. - /// - /// The comparison used to match property names while merging. - public StringComparison PropertyNameComparison - { - get => _propertyNameComparison; - set - { - if (value < StringComparison.CurrentCulture || value > StringComparison.OrdinalIgnoreCase) - throw new ArgumentOutOfRangeException(nameof(value)); - - _propertyNameComparison = value; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs deleted file mode 100644 index 253ecd1ab..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class ArrayIndexFilter : PathFilter - { - public int? Index { get; set; } - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - if (Index != null) - { - var v = GetTokenIndex(t, settings, Index.GetValueOrDefault()); - - if (v != null) yield return v; - } - else - { - if (t is JArray || t is JConstructor) - { - foreach (var v in t) yield return v; - } - else - { - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name)); - } - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs deleted file mode 100644 index e903519ac..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class ArrayMultipleIndexFilter : PathFilter - { - public ArrayMultipleIndexFilter(List indexes) => Indexes = indexes; - - internal List Indexes; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - foreach (var i in Indexes) - { - var v = GetTokenIndex(t, settings, i); - - if (v != null) yield return v; - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs deleted file mode 100644 index 607d6ae8a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class ArraySliceFilter : PathFilter - { - public int? End { get; set; } - public int? Start { get; set; } - public int? Step { get; set; } - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - if (Step == 0) throw new JsonException("Step cannot be zero."); - - foreach (var t in current) - { - if (t is JArray a) - { - // set defaults for null arguments - var stepCount = Step ?? 1; - var startIndex = Start ?? (stepCount > 0 ? 0 : a.Count - 1); - var stopIndex = End ?? (stepCount > 0 ? a.Count : -1); - - // start from the end of the list if start is negative - if (Start < 0) startIndex = a.Count + startIndex; - - // end from the start of the list if stop is negative - if (End < 0) stopIndex = a.Count + stopIndex; - - // ensure indexes keep within collection bounds - startIndex = Math.Max(startIndex, stepCount > 0 ? 0 : int.MinValue); - startIndex = Math.Min(startIndex, stepCount > 0 ? a.Count : a.Count - 1); - stopIndex = Math.Max(stopIndex, -1); - stopIndex = Math.Min(stopIndex, a.Count); - - var positiveStep = stepCount > 0; - - if (IsValid(startIndex, stopIndex, positiveStep)) - { - for (var i = startIndex; IsValid(i, stopIndex, positiveStep); i += stepCount) yield return a[i]; - } - else - { - if (settings?.ErrorWhenNoMatch ?? false) - { - throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture, - Start != null ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*", - End != null ? End.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*")); - } - } - } - else - { - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name)); - } - } - } - - private bool IsValid(int index, int stopIndex, bool positiveStep) - { - if (positiveStep) return index < stopIndex; - - return index > stopIndex; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs deleted file mode 100644 index 7321eb10a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class FieldFilter : PathFilter - { - public FieldFilter(string? name) => Name = name; - - internal string? Name; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - if (t is JObject o) - { - if (Name != null) - { - var v = o[Name]; - - if (v != null) - yield return v; - else if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name)); - } - else - { - foreach (var p in o) yield return p.Value!; - } - } - else - { - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException( - "Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", t.GetType().Name)); - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs deleted file mode 100644 index a35fdf3a3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class FieldMultipleFilter : PathFilter - { - public FieldMultipleFilter(List names) => Names = names; - - internal List Names; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - if (t is JObject o) - { - foreach (var name in Names) - { - var v = o[name]; - - if (v != null) yield return v; - - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name)); - } - } - else - { - if (settings?.ErrorWhenNoMatch ?? false) - { - throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", - Names.Select(n => "'" + n + "'") -#if !HAVE_STRING_JOIN_WITH_ENUMERABLE - .ToArray() -#endif - ), t.GetType().Name)); - } - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/JPath.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/JPath.cs deleted file mode 100644 index 5fbb06b04..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/JPath.cs +++ /dev/null @@ -1,742 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class JPath - { - private static readonly char[] FloatCharacters = { '.', 'E', 'e' }; - - private readonly string _expression; - - public JPath(string expression) - { - ValidationUtils.ArgumentNotNull(expression, nameof(expression)); - _expression = expression; - Filters = new List(); - - ParseMain(); - } - - private int _currentIndex; - public List Filters { get; } - - private void ParseMain() - { - var currentPartStartIndex = _currentIndex; - - EatWhitespace(); - - if (_expression.Length == _currentIndex) return; - - if (_expression[_currentIndex] == '$') - { - if (_expression.Length == 1) return; - - // only increment position for "$." or "$[" - // otherwise assume property that starts with $ - var c = _expression[_currentIndex + 1]; - if (c == '.' || c == '[') - { - _currentIndex++; - currentPartStartIndex = _currentIndex; - } - } - - if (!ParsePath(Filters, currentPartStartIndex, false)) - { - var lastCharacterIndex = _currentIndex; - - EatWhitespace(); - - if (_currentIndex < _expression.Length) - throw new JsonException("Unexpected character while parsing path: " + _expression[lastCharacterIndex]); - } - } - - private bool ParsePath(List filters, int currentPartStartIndex, bool query) - { - var scan = false; - var followingIndexer = false; - var followingDot = false; - - var ended = false; - while (_currentIndex < _expression.Length && !ended) - { - var currentChar = _expression[_currentIndex]; - - switch (currentChar) - { - case '[': - case '(': - if (_currentIndex > currentPartStartIndex) - { - var member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); - if (member == "*") member = null; - - filters.Add(CreatePathFilter(member, scan)); - scan = false; - } - - filters.Add(ParseIndexer(currentChar, scan)); - scan = false; - - _currentIndex++; - currentPartStartIndex = _currentIndex; - followingIndexer = true; - followingDot = false; - break; - case ']': - case ')': - ended = true; - break; - case ' ': - if (_currentIndex < _expression.Length) ended = true; - break; - case '.': - if (_currentIndex > currentPartStartIndex) - { - var member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); - if (member == "*") member = null; - - filters.Add(CreatePathFilter(member, scan)); - scan = false; - } - if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.') - { - scan = true; - _currentIndex++; - } - _currentIndex++; - currentPartStartIndex = _currentIndex; - followingIndexer = false; - followingDot = true; - break; - default: - if (query && (currentChar == '=' || currentChar == '<' || currentChar == '!' || currentChar == '>' || currentChar == '|' - || currentChar == '&')) - ended = true; - else - { - if (followingIndexer) throw new JsonException("Unexpected character following indexer: " + currentChar); - - _currentIndex++; - } - break; - } - } - - var atPathEnd = _currentIndex == _expression.Length; - - if (_currentIndex > currentPartStartIndex) - { - var member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(); - if (member == "*") member = null; - filters.Add(CreatePathFilter(member, scan)); - } - else - { - // no field name following dot in path and at end of base path/query - if (followingDot && (atPathEnd || query)) throw new JsonException("Unexpected end while parsing path."); - } - - return atPathEnd; - } - - private static PathFilter CreatePathFilter(string? member, bool scan) - { - var filter = scan ? (PathFilter)new ScanFilter(member) : new FieldFilter(member); - return filter; - } - - private PathFilter ParseIndexer(char indexerOpenChar, bool scan) - { - _currentIndex++; - - var indexerCloseChar = indexerOpenChar == '[' ? ']' : ')'; - - EnsureLength("Path ended with open indexer."); - - EatWhitespace(); - - if (_expression[_currentIndex] == '\'') - return ParseQuotedField(indexerCloseChar, scan); - if (_expression[_currentIndex] == '?') - return ParseQuery(indexerCloseChar, scan); - - return ParseArrayIndexer(indexerCloseChar); - } - - private PathFilter ParseArrayIndexer(char indexerCloseChar) - { - var start = _currentIndex; - int? end = null; - List? indexes = null; - var colonCount = 0; - int? startIndex = null; - int? endIndex = null; - int? step = null; - - while (_currentIndex < _expression.Length) - { - var currentCharacter = _expression[_currentIndex]; - - if (currentCharacter == ' ') - { - end = _currentIndex; - EatWhitespace(); - continue; - } - - if (currentCharacter == indexerCloseChar) - { - var length = (end ?? _currentIndex) - start; - - if (indexes != null) - { - if (length == 0) throw new JsonException("Array index expected."); - - var indexer = _expression.Substring(start, length); - var index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); - - indexes.Add(index); - return new ArrayMultipleIndexFilter(indexes); - } - if (colonCount > 0) - { - if (length > 0) - { - var indexer = _expression.Substring(start, length); - var index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); - - if (colonCount == 1) - endIndex = index; - else - step = index; - } - - return new ArraySliceFilter { Start = startIndex, End = endIndex, Step = step }; - } - { - if (length == 0) throw new JsonException("Array index expected."); - - var indexer = _expression.Substring(start, length); - var index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); - - return new ArrayIndexFilter { Index = index }; - } - } - if (currentCharacter == ',') - { - var length = (end ?? _currentIndex) - start; - - if (length == 0) throw new JsonException("Array index expected."); - - if (indexes == null) indexes = new List(); - - var indexer = _expression.Substring(start, length); - indexes.Add(Convert.ToInt32(indexer, CultureInfo.InvariantCulture)); - - _currentIndex++; - - EatWhitespace(); - - start = _currentIndex; - end = null; - } - else if (currentCharacter == '*') - { - _currentIndex++; - EnsureLength("Path ended with open indexer."); - EatWhitespace(); - - if (_expression[_currentIndex] != indexerCloseChar) - throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter); - - return new ArrayIndexFilter(); - } - else if (currentCharacter == ':') - { - var length = (end ?? _currentIndex) - start; - - if (length > 0) - { - var indexer = _expression.Substring(start, length); - var index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); - - if (colonCount == 0) - startIndex = index; - else if (colonCount == 1) - endIndex = index; - else - step = index; - } - - colonCount++; - - _currentIndex++; - - EatWhitespace(); - - start = _currentIndex; - end = null; - } - else if (!char.IsDigit(currentCharacter) && currentCharacter != '-') - throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter); - else - { - if (end != null) throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter); - - _currentIndex++; - } - } - - throw new JsonException("Path ended with open indexer."); - } - - private void EatWhitespace() - { - while (_currentIndex < _expression.Length) - { - if (_expression[_currentIndex] != ' ') break; - - _currentIndex++; - } - } - - private PathFilter ParseQuery(char indexerCloseChar, bool scan) - { - _currentIndex++; - EnsureLength("Path ended with open indexer."); - - if (_expression[_currentIndex] != '(') - throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); - - _currentIndex++; - - var expression = ParseExpression(); - - _currentIndex++; - EnsureLength("Path ended with open indexer."); - EatWhitespace(); - - if (_expression[_currentIndex] != indexerCloseChar) - throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); - - if (!scan) - return new QueryFilter(expression); - - return new QueryScanFilter(expression); - } - - private bool TryParseExpression(out List? expressionPath) - { - if (_expression[_currentIndex] == '$') - expressionPath = new List { RootFilter.Instance }; - else if (_expression[_currentIndex] == '@') - expressionPath = new List(); - else - { - expressionPath = null; - return false; - } - - _currentIndex++; - - if (ParsePath(expressionPath!, _currentIndex, true)) throw new JsonException("Path ended with open query."); - - return true; - } - - private JsonException CreateUnexpectedCharacterException() => - new("Unexpected character while parsing path query: " + _expression[_currentIndex]); - - private object ParseSide() - { - EatWhitespace(); - - if (TryParseExpression(out var expressionPath)) - { - EatWhitespace(); - EnsureLength("Path ended with open query."); - - return expressionPath!; - } - - if (TryParseValue(out var value)) - { - EatWhitespace(); - EnsureLength("Path ended with open query."); - - return new JValue(value); - } - - throw CreateUnexpectedCharacterException(); - } - - private QueryExpression ParseExpression() - { - QueryExpression? rootExpression = null; - CompositeExpression? parentExpression = null; - - while (_currentIndex < _expression.Length) - { - var left = ParseSide(); - object? right = null; - - QueryOperator op; - if (_expression[_currentIndex] == ')' - || _expression[_currentIndex] == '|' - || _expression[_currentIndex] == '&') - op = QueryOperator.Exists; - else - { - op = ParseOperator(); - - right = ParseSide(); - } - - var booleanExpression = new BooleanQueryExpression(op, left, right); - - if (_expression[_currentIndex] == ')') - { - if (parentExpression != null) - { - parentExpression.Expressions.Add(booleanExpression); - return rootExpression!; - } - - return booleanExpression; - } - if (_expression[_currentIndex] == '&') - { - if (!Match("&&")) throw CreateUnexpectedCharacterException(); - - if (parentExpression == null || parentExpression.Operator != QueryOperator.And) - { - var andExpression = new CompositeExpression(QueryOperator.And); - - parentExpression?.Expressions.Add(andExpression); - - parentExpression = andExpression; - - if (rootExpression == null) rootExpression = parentExpression; - } - - parentExpression.Expressions.Add(booleanExpression); - } - if (_expression[_currentIndex] == '|') - { - if (!Match("||")) throw CreateUnexpectedCharacterException(); - - if (parentExpression == null || parentExpression.Operator != QueryOperator.Or) - { - var orExpression = new CompositeExpression(QueryOperator.Or); - - parentExpression?.Expressions.Add(orExpression); - - parentExpression = orExpression; - - if (rootExpression == null) rootExpression = parentExpression; - } - - parentExpression.Expressions.Add(booleanExpression); - } - } - - throw new JsonException("Path ended with open query."); - } - - private bool TryParseValue(out object? value) - { - var currentChar = _expression[_currentIndex]; - if (currentChar == '\'') - { - value = ReadQuotedString(); - return true; - } - if (char.IsDigit(currentChar) || currentChar == '-') - { - var sb = new StringBuilder(); - sb.Append(currentChar); - - _currentIndex++; - while (_currentIndex < _expression.Length) - { - currentChar = _expression[_currentIndex]; - if (currentChar == ' ' || currentChar == ')') - { - var numberText = sb.ToString(); - - if (numberText.IndexOfAny(FloatCharacters) != -1) - { - var result = double.TryParse(numberText, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, - out var d); - value = d; - return result; - } - else - { - var result = long.TryParse(numberText, NumberStyles.Integer, CultureInfo.InvariantCulture, out var l); - value = l; - return result; - } - } - sb.Append(currentChar); - _currentIndex++; - } - } - else if (currentChar == 't') - { - if (Match("true")) - { - value = true; - return true; - } - } - else if (currentChar == 'f') - { - if (Match("false")) - { - value = false; - return true; - } - } - else if (currentChar == 'n') - { - if (Match("null")) - { - value = null; - return true; - } - } - else if (currentChar == '/') - { - value = ReadRegexString(); - return true; - } - - value = null; - return false; - } - - private string ReadQuotedString() - { - var sb = new StringBuilder(); - - _currentIndex++; - while (_currentIndex < _expression.Length) - { - var currentChar = _expression[_currentIndex]; - if (currentChar == '\\' && _currentIndex + 1 < _expression.Length) - { - _currentIndex++; - currentChar = _expression[_currentIndex]; - - char resolvedChar; - switch (currentChar) - { - case 'b': - resolvedChar = '\b'; - break; - case 't': - resolvedChar = '\t'; - break; - case 'n': - resolvedChar = '\n'; - break; - case 'f': - resolvedChar = '\f'; - break; - case 'r': - resolvedChar = '\r'; - break; - case '\\': - case '"': - case '\'': - case '/': - resolvedChar = currentChar; - break; - default: - throw new JsonException(@"Unknown escape character: \" + currentChar); - } - - sb.Append(resolvedChar); - - _currentIndex++; - } - else if (currentChar == '\'') - { - _currentIndex++; - return sb.ToString(); - } - else - { - _currentIndex++; - sb.Append(currentChar); - } - } - - throw new JsonException("Path ended with an open string."); - } - - private string ReadRegexString() - { - var startIndex = _currentIndex; - - _currentIndex++; - while (_currentIndex < _expression.Length) - { - var currentChar = _expression[_currentIndex]; - - // handle escaped / character - if (currentChar == '\\' && _currentIndex + 1 < _expression.Length) - _currentIndex += 2; - else if (currentChar == '/') - { - _currentIndex++; - - while (_currentIndex < _expression.Length) - { - currentChar = _expression[_currentIndex]; - - if (char.IsLetter(currentChar)) - _currentIndex++; - else - break; - } - - return _expression.Substring(startIndex, _currentIndex - startIndex); - } - else - _currentIndex++; - } - - throw new JsonException("Path ended with an open regex."); - } - - private bool Match(string s) - { - var currentPosition = _currentIndex; - for (var i = 0; i < s.Length; i++) - { - if (currentPosition < _expression.Length && _expression[currentPosition] == s[i]) - currentPosition++; - else - return false; - } - - _currentIndex = currentPosition; - return true; - } - - private QueryOperator ParseOperator() - { - if (_currentIndex + 1 >= _expression.Length) throw new JsonException("Path ended with open query."); - - if (Match("===")) return QueryOperator.StrictEquals; - - if (Match("==")) return QueryOperator.Equals; - - if (Match("=~")) return QueryOperator.RegexEquals; - - if (Match("!==")) return QueryOperator.StrictNotEquals; - - if (Match("!=") || Match("<>")) return QueryOperator.NotEquals; - - if (Match("<=")) return QueryOperator.LessThanOrEquals; - - if (Match("<")) return QueryOperator.LessThan; - - if (Match(">=")) return QueryOperator.GreaterThanOrEquals; - - if (Match(">")) return QueryOperator.GreaterThan; - - throw new JsonException("Could not read query operator."); - } - - private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) - { - List? fields = null; - - while (_currentIndex < _expression.Length) - { - var field = ReadQuotedString(); - - EatWhitespace(); - EnsureLength("Path ended with open indexer."); - - if (_expression[_currentIndex] == indexerCloseChar) - { - if (fields != null) - { - fields.Add(field); - return scan - ? new ScanMultipleFilter(fields) - : (PathFilter)new FieldMultipleFilter(fields); - } - return CreatePathFilter(field, scan); - } - if (_expression[_currentIndex] == ',') - { - _currentIndex++; - EatWhitespace(); - - if (fields == null) fields = new List(); - - fields.Add(field); - } - else - throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); - } - - throw new JsonException("Path ended with open indexer."); - } - - private void EnsureLength(string message) - { - if (_currentIndex >= _expression.Length) throw new JsonException(message); - } - - internal IEnumerable Evaluate(JToken root, JToken t, JsonSelectSettings? settings) => Evaluate(Filters, root, t, settings); - - internal static IEnumerable Evaluate(List filters, JToken root, JToken t, JsonSelectSettings? settings) - { - IEnumerable current = new[] { t }; - foreach (var filter in filters) current = filter.ExecuteFilter(root, current, settings); - - return current; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs deleted file mode 100644 index 9429ee1f7..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal abstract class PathFilter - { - public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings); - - protected static JToken? GetTokenIndex(JToken t, JsonSelectSettings? settings, int index) - { - if (t is JArray a) - { - if (a.Count <= index) - { - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index)); - - return null; - } - - return a[index]; - } - if (t is JConstructor c) - { - if (c.Count <= index) - { - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index)); - - return null; - } - - return c[index]; - } - if (settings?.ErrorWhenNoMatch ?? false) - throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name)); - - return null; - } - - protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value) - { - // step into container's values - if (container != null && container.HasValues) - value = container.First; - else - { - // finished container, move to parent - while (value != null && value != originalParent && value == value.Parent!.Last) value = value.Parent; - - // finished - if (value == null || value == originalParent) return null; - - // move to next value in container - value = value.Next; - } - - return value; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs deleted file mode 100644 index b99953eb5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs +++ /dev/null @@ -1,267 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text.RegularExpressions; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal enum QueryOperator - { - None = 0, - Equals = 1, - NotEquals = 2, - Exists = 3, - LessThan = 4, - LessThanOrEquals = 5, - GreaterThan = 6, - GreaterThanOrEquals = 7, - And = 8, - Or = 9, - RegexEquals = 10, - StrictEquals = 11, - StrictNotEquals = 12 - } - - internal abstract class QueryExpression - { - public QueryExpression(QueryOperator @operator) => Operator = @operator; - - public abstract bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings); - - internal QueryOperator Operator; - - // For unit tests - public bool IsMatch(JToken root, JToken t) => IsMatch(root, t, null); - } - - internal class CompositeExpression : QueryExpression - { - public CompositeExpression(QueryOperator @operator) : base(@operator) => Expressions = new List(); - - public List Expressions { get; set; } - - public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) - { - switch (Operator) - { - case QueryOperator.And: - foreach (var e in Expressions) - { - if (!e.IsMatch(root, t, settings)) return false; - } - return true; - case QueryOperator.Or: - foreach (var e in Expressions) - { - if (e.IsMatch(root, t, settings)) return true; - } - return false; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - internal class BooleanQueryExpression : QueryExpression - { - public readonly object Left; - public readonly object? Right; - - public BooleanQueryExpression(QueryOperator @operator, object left, object? right) : base(@operator) - { - Left = left; - Right = right; - } - - private IEnumerable GetResult(JToken root, JToken t, object? o) - { - if (o is JToken resultToken) return new[] { resultToken }; - - if (o is List pathFilters) return JPath.Evaluate(pathFilters, root, t, null); - - return CollectionUtils.ArrayEmpty(); - } - - public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) - { - if (Operator == QueryOperator.Exists) return GetResult(root, t, Left).Any(); - - using (var leftResults = GetResult(root, t, Left).GetEnumerator()) - { - if (leftResults.MoveNext()) - { - var rightResultsEn = GetResult(root, t, Right); - var rightResults = rightResultsEn as ICollection ?? rightResultsEn.ToList(); - - do - { - var leftResult = leftResults.Current; - foreach (var rightResult in rightResults) - { - if (MatchTokens(leftResult, rightResult, settings)) return true; - } - } while (leftResults.MoveNext()); - } - } - - return false; - } - - private bool MatchTokens(JToken leftResult, JToken rightResult, JsonSelectSettings? settings) - { - if (leftResult is JValue leftValue && rightResult is JValue rightValue) - { - switch (Operator) - { - case QueryOperator.RegexEquals: - if (RegexEquals(leftValue, rightValue, settings)) return true; - - break; - case QueryOperator.Equals: - if (EqualsWithStringCoercion(leftValue, rightValue)) return true; - - break; - case QueryOperator.StrictEquals: - if (EqualsWithStrictMatch(leftValue, rightValue)) return true; - - break; - case QueryOperator.NotEquals: - if (!EqualsWithStringCoercion(leftValue, rightValue)) return true; - - break; - case QueryOperator.StrictNotEquals: - if (!EqualsWithStrictMatch(leftValue, rightValue)) return true; - - break; - case QueryOperator.GreaterThan: - if (leftValue.CompareTo(rightValue) > 0) return true; - - break; - case QueryOperator.GreaterThanOrEquals: - if (leftValue.CompareTo(rightValue) >= 0) return true; - - break; - case QueryOperator.LessThan: - if (leftValue.CompareTo(rightValue) < 0) return true; - - break; - case QueryOperator.LessThanOrEquals: - if (leftValue.CompareTo(rightValue) <= 0) return true; - - break; - case QueryOperator.Exists: - return true; - } - } - else - { - switch (Operator) - { - case QueryOperator.Exists: - // you can only specify primitive types in a comparison - // notequals will always be true - case QueryOperator.NotEquals: - return true; - } - } - - return false; - } - - private static bool RegexEquals(JValue input, JValue pattern, JsonSelectSettings? settings) - { - if (input.Type != JTokenType.String || pattern.Type != JTokenType.String) return false; - - var regexText = (string)pattern.Value!; - var patternOptionDelimiterIndex = regexText.LastIndexOf('/'); - - var patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1); - var optionsText = regexText.Substring(patternOptionDelimiterIndex + 1); - -#if HAVE_REGEX_TIMEOUTS - TimeSpan timeout = settings?.RegexMatchTimeout ?? Regex.InfiniteMatchTimeout; - return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText), timeout); -#else - return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText)); -#endif - } - - internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) - { - if (value.Equals(queryValue)) return true; - - // Handle comparing an integer with a float - // e.g. Comparing 1 and 1.0 - if (value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float - || value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer) - return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; - - if (queryValue.Type != JTokenType.String) return false; - - var queryValueString = (string)queryValue.Value!; - - string currentValueString; - - // potential performance issue with converting every value to string? - switch (value.Type) - { - case JTokenType.Date: - using (var writer = StringUtils.CreateStringWriter(64)) - { -#if HAVE_DATE_TIME_OFFSET - if (value.Value is DateTimeOffset offset) - { - DateTimeUtils.WriteDateTimeOffsetString(writer, offset, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); - } - else -#endif - { - DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value!, DateFormatHandling.IsoDateFormat, null, - CultureInfo.InvariantCulture); - } - - currentValueString = writer.ToString(); - } - break; - case JTokenType.Bytes: - currentValueString = Convert.ToBase64String((byte[])value.Value!); - break; - case JTokenType.Guid: - case JTokenType.TimeSpan: - currentValueString = value.Value!.ToString(); - break; - case JTokenType.Uri: - currentValueString = ((Uri)value.Value!).OriginalString; - break; - default: - return false; - } - - return string.Equals(currentValueString, queryValueString, StringComparison.Ordinal); - } - - internal static bool EqualsWithStrictMatch(JValue value, JValue queryValue) - { - MiscellaneousUtils.Assert(value != null); - MiscellaneousUtils.Assert(queryValue != null); - - // Handle comparing an integer with a float - // e.g. Comparing 1 and 1.0 - if (value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float - || value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer) - return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; - - // we handle floats and integers the exact same way, so they are pseudo equivalent - if (value.Type != queryValue.Type) return false; - - return value.Equals(queryValue); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs deleted file mode 100644 index ae851c17e..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class QueryFilter : PathFilter - { - public QueryFilter(QueryExpression expression) => Expression = expression; - - internal QueryExpression Expression; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - foreach (var v in t) - { - if (Expression.IsMatch(root, v, settings)) yield return v; - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs deleted file mode 100644 index 1cf8be590..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class QueryScanFilter : PathFilter - { - public QueryScanFilter(QueryExpression expression) => Expression = expression; - - internal QueryExpression Expression; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var t in current) - { - if (t is JContainer c) - { - foreach (var d in c.DescendantsAndSelf()) - { - if (Expression.IsMatch(root, d, settings)) yield return d; - } - } - else - { - if (Expression.IsMatch(root, t, settings)) yield return t; - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/RootFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/RootFilter.cs deleted file mode 100644 index 37263623a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/RootFilter.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class RootFilter : PathFilter - { - public static readonly RootFilter Instance = new(); - - private RootFilter() { } - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) => new[] { root }; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs deleted file mode 100644 index 175fcd866..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class ScanFilter : PathFilter - { - public ScanFilter(string? name) => Name = name; - - internal string? Name; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var c in current) - { - if (Name == null) yield return c; - - var value = c; - - while (true) - { - var container = value as JContainer; - - value = GetNextScanValue(c, container, value); - if (value == null) break; - - if (value is JProperty property) - { - if (property.Name == Name) yield return property.Value; - } - else - { - if (Name == null) yield return value; - } - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs deleted file mode 100644 index 64dcffbf9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq.JsonPath -{ - internal class ScanMultipleFilter : PathFilter - { - public ScanMultipleFilter(List names) => _names = names; - - private readonly List _names; - - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) - { - foreach (var c in current) - { - var value = c; - - while (true) - { - var container = value as JContainer; - - value = GetNextScanValue(c, container, value); - if (value == null) break; - - if (value is JProperty property) - { - foreach (var name in _names) - { - if (property.Name == name) yield return property.Value; - } - } - } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonSelectSettings.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonSelectSettings.cs deleted file mode 100644 index 3fa266002..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/JsonSelectSettings.cs +++ /dev/null @@ -1,27 +0,0 @@ -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies the settings used when selecting JSON. - /// - internal class JsonSelectSettings - { -#if HAVE_REGEX_TIMEOUTS - /// - /// Gets or sets a timeout that will be used when executing regular expressions. - /// - /// The timeout that will be used when executing regular expressions. - public TimeSpan? RegexMatchTimeout { get; set; } -#endif - - /// - /// Gets or sets a flag that indicates whether an error should be thrown if - /// no tokens are found when evaluating part of the expression. - /// - /// - /// A flag that indicates whether an error should be thrown if - /// no tokens are found when evaluating part of the expression. - /// - public bool ErrorWhenNoMatch { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/LineInfoHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/LineInfoHandling.cs deleted file mode 100644 index 24b909184..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/LineInfoHandling.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies how line information is handled when loading JSON. - /// - internal enum LineInfoHandling - { - /// - /// Ignore line information. - /// - Ignore = 0, - - /// - /// Load line information. - /// - Load = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeArrayHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeArrayHandling.cs deleted file mode 100644 index 2949abb28..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeArrayHandling.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies how JSON arrays are merged together. - /// - internal enum MergeArrayHandling - { - /// Concatenate arrays. - Concat = 0, - - /// Union arrays, skipping items that already exist. - Union = 1, - - /// Replace all array items. - Replace = 2, - - /// Merge array items together, matched by index. - Merge = 3 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeNullValueHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeNullValueHandling.cs deleted file mode 100644 index e70d3dc4c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Linq/MergeNullValueHandling.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Linq -{ - /// - /// Specifies how null value properties are merged. - /// - [Flags] - internal enum MergeNullValueHandling - { - /// - /// The content's null value properties will be ignored during merging. - /// - Ignore = 0, - - /// - /// The content's null value properties will be merged. - /// - Merge = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MemberSerialization.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/MemberSerialization.cs deleted file mode 100644 index c6e3711e8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MemberSerialization.cs +++ /dev/null @@ -1,63 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies the member serialization options for the . - /// - internal enum MemberSerialization - { -#pragma warning disable 1584,1711,1572,1581,1580,1574 - /// - /// All public members are serialized by default. Members can be excluded using or - /// . - /// This is the default member serialization mode. - /// - OptOut = 0, - - /// - /// Only members marked with or are serialized. - /// This member serialization mode can also be set by marking the class with . - /// - OptIn = 1, - - /// - /// All public and private fields are serialized. Members can be excluded using or - /// . - /// This member serialization mode can also be set by marking the class with - /// and setting IgnoreSerializableAttribute on to false. - /// - Fields = 2 -#pragma warning restore 1584,1711,1572,1581,1580,1574 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MetadataPropertyHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/MetadataPropertyHandling.cs deleted file mode 100644 index 0cc657c29..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MetadataPropertyHandling.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies metadata property handling options for the . - /// - internal enum MetadataPropertyHandling - { - /// - /// Read metadata properties located at the start of a JSON object. - /// - Default = 0, - - /// - /// Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance. - /// - ReadAhead = 1, - - /// - /// Do not try to read metadata properties. - /// - Ignore = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MissingMemberHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/MissingMemberHandling.cs deleted file mode 100644 index f64ea701c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/MissingMemberHandling.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies missing member handling options for the . - /// - internal enum MissingMemberHandling - { - /// - /// Ignore a missing member and do not attempt to deserialize it. - /// - Ignore = 0, - - /// - /// Throw a when a missing member is encountered during deserialization. - /// - Error = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/NullValueHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/NullValueHandling.cs deleted file mode 100644 index 21b74cb19..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/NullValueHandling.cs +++ /dev/null @@ -1,52 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies null value handling options for the . - /// - /// - /// - /// - /// - internal enum NullValueHandling - { - /// - /// Include null values when serializing and deserializing objects. - /// - Include = 0, - - /// - /// Ignore null values when serializing and deserializing objects. - /// - Ignore = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ObjectCreationHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/ObjectCreationHandling.cs deleted file mode 100644 index 43bc4cbd5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ObjectCreationHandling.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how object creation is handled by the . - /// - internal enum ObjectCreationHandling - { - /// - /// Reuse existing objects, create new objects when needed. - /// - Auto = 0, - - /// - /// Only reuse existing objects. - /// - Reuse = 1, - - /// - /// Always create new objects. - /// - Replace = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/PreserveReferencesHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/PreserveReferencesHandling.cs deleted file mode 100644 index 52b6db3d5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/PreserveReferencesHandling.cs +++ /dev/null @@ -1,65 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies reference handling options for the . - /// Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement - /// . - /// - /// - /// - /// - [Flags] - internal enum PreserveReferencesHandling - { - /// - /// Do not preserve references when serializing types. - /// - None = 0, - - /// - /// Preserve references when serializing into a JSON object structure. - /// - Objects = 1, - - /// - /// Preserve references when serializing into a JSON array structure. - /// - Arrays = 2, - - /// - /// Preserve references when serializing. - /// - All = Objects | Arrays - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ReferenceLoopHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/ReferenceLoopHandling.cs deleted file mode 100644 index 61f822026..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/ReferenceLoopHandling.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies reference loop handling options for the . - /// - internal enum ReferenceLoopHandling - { - /// - /// Throw a when a loop is encountered. - /// - Error = 0, - - /// - /// Ignore loop references and do not serialize. - /// - Ignore = 1, - - /// - /// Serialize loop references. - /// - Serialize = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Required.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Required.cs deleted file mode 100644 index deff34123..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Required.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Indicating whether a property is required. - /// - internal enum Required - { - /// - /// The property is not required. The default state. - /// - Default = 0, - - /// - /// The property must be defined in JSON but can be a null value. - /// - AllowNull = 1, - - /// - /// The property must be defined in JSON and cannot be a null value. - /// - Always = 2, - - /// - /// The property is not required but it cannot be a null value. - /// - DisallowNull = 3 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/Extensions.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/Extensions.cs deleted file mode 100644 index 647dd67f0..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/Extensions.cs +++ /dev/null @@ -1,138 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Contains the JSON schema extension methods. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal static class Extensions - { - /// - /// - /// Determines whether the is valid. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - /// The source to test. - /// The schema to test with. - /// - /// true if the specified is valid; otherwise, false. - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - public static bool IsValid(this JToken source, JsonSchema schema) - { - var valid = true; - source.Validate(schema, (sender, args) => { valid = false; }); - return valid; - } - - /// - /// - /// Determines whether the is valid. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - /// The source to test. - /// The schema to test with. - /// When this method returns, contains any error messages generated while validating. - /// - /// true if the specified is valid; otherwise, false. - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - public static bool IsValid(this JToken source, JsonSchema schema, out IList errorMessages) - { - IList errors = new List(); - - source.Validate(schema, (sender, args) => errors.Add(args.Message)); - - errorMessages = errors; - return errorMessages.Count == 0; - } - - /// - /// - /// Validates the specified . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - /// The source to test. - /// The schema to test with. - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - public static void Validate(this JToken source, JsonSchema schema) => source.Validate(schema, null); - - /// - /// - /// Validates the specified . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - /// The source to test. - /// The schema to test with. - /// The validation event handler. - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler) - { - ValidationUtils.ArgumentNotNull(source, nameof(source)); - ValidationUtils.ArgumentNotNull(schema, nameof(schema)); - - using (var reader = new JsonValidatingReader(source.CreateReader())) - { - reader.Schema = schema; - if (validationEventHandler != null) reader.ValidationEventHandler += validationEventHandler; - - while (reader.Read()) { } - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchema.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchema.cs deleted file mode 100644 index 43e97b6bd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchema.cs +++ /dev/null @@ -1,358 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// An in-memory representation of a JSON Schema. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchema - { -#pragma warning disable CA1305 // Specify IFormatProvider -#pragma warning restore CA1305 // Specify IFormatProvider - - /// - /// Initializes a new instance of the class. - /// - public JsonSchema() - { - AllowAdditionalProperties = true; - AllowAdditionalItems = true; - } - - /// - /// Gets or sets the of additional items. - /// - /// The of additional items. - public JsonSchema AdditionalItems { get; set; } - - /// - /// Gets or sets the of additional properties. - /// - /// The of additional properties. - public JsonSchema AdditionalProperties { get; set; } - - /// - /// Gets or sets a value indicating whether additional items are allowed. - /// - /// - /// true if additional items are allowed; otherwise, false. - /// - public bool AllowAdditionalItems { get; set; } - - /// - /// Gets or sets a value indicating whether additional properties are allowed. - /// - /// - /// true if additional properties are allowed; otherwise, false. - /// - public bool AllowAdditionalProperties { get; set; } - - /// - /// Gets or sets the default value. - /// - /// The default value. - public JToken Default { get; set; } - - // if this is set then this schema instance is just a deferred reference - // and will be replaced when the schema reference is resolved - internal string DeferredReference { get; set; } - - /// - /// Gets or sets the description of the object. - /// - public string Description { get; set; } - - /// - /// Gets or sets disallowed types. - /// - /// The disallowed types. - public JsonSchemaType? Disallow { get; set; } - - /// - /// Gets or sets a number that the value should be divisible by. - /// - /// A number that the value should be divisible by. - public double? DivisibleBy { get; set; } - - /// - /// Gets or sets the a collection of valid enum values allowed. - /// - /// A collection of valid enum values allowed. - public IList Enum { get; set; } - - /// - /// Gets or sets a flag indicating whether the value can not equal the number defined by the maximum attribute ( - /// ). - /// - /// - /// A flag indicating whether the value can not equal the number defined by the maximum attribute ( - /// ). - /// - public bool? ExclusiveMaximum { get; set; } - - /// - /// Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute ( - /// ). - /// - /// - /// A flag indicating whether the value can not equal the number defined by the minimum attribute ( - /// ). - /// - public bool? ExclusiveMinimum { get; set; } - - /// - /// Gets or sets the collection of that this schema extends. - /// - /// The collection of that this schema extends. - public IList Extends { get; set; } - - /// - /// Gets or sets the format. - /// - /// The format. - public string Format { get; set; } - - /// - /// Gets or sets whether the object is visible to users. - /// - public bool? Hidden { get; set; } - - /// - /// Gets or sets the id. - /// - public string Id { get; set; } - - internal string InternalId { get; } = Guid.NewGuid().ToString("N"); - - /// - /// Gets or sets the of items. - /// - /// The of items. - public IList Items { get; set; } - - internal string Location { get; set; } - - /// - /// Gets or sets the maximum. - /// - /// The maximum. - public double? Maximum { get; set; } - - /// - /// Gets or sets the maximum number of items. - /// - /// The maximum number of items. - public int? MaximumItems { get; set; } - - /// - /// Gets or sets the maximum length. - /// - /// The maximum length. - public int? MaximumLength { get; set; } - - /// - /// Gets or sets the minimum. - /// - /// The minimum. - public double? Minimum { get; set; } - - /// - /// Gets or sets the minimum number of items. - /// - /// The minimum number of items. - public int? MinimumItems { get; set; } - - /// - /// Gets or sets the minimum length. - /// - /// The minimum length. - public int? MinimumLength { get; set; } - - /// - /// Gets or sets the pattern. - /// - /// The pattern. - public string Pattern { get; set; } - - /// - /// Gets or sets the pattern properties. - /// - /// The pattern properties. - public IDictionary PatternProperties { get; set; } - - /// - /// Gets or sets a value indicating whether items in an array are validated using the instance at - /// their array position from . - /// - /// - /// true if items are validated using their array position; otherwise, false. - /// - public bool PositionalItemsValidation { get; set; } - - /// - /// Gets or sets the of properties. - /// - /// The of properties. - public IDictionary Properties { get; set; } - - /// - /// Gets or sets whether the object is read-only. - /// - public bool? ReadOnly { get; set; } - - internal bool ReferencesResolved { get; set; } - - /// - /// Gets or sets whether the object is required. - /// - public bool? Required { get; set; } - - /// - /// Gets or sets the required property if this property is present. - /// - /// The required property if this property is present. - public string Requires { get; set; } - - /// - /// Gets or sets the title. - /// - public string Title { get; set; } - - /// - /// Gets or sets whether the object is transient. - /// - public bool? Transient { get; set; } - - /// - /// Gets or sets the types of values allowed by the object. - /// - /// The type. - public JsonSchemaType? Type { get; set; } - - /// - /// Gets or sets whether the array items must be unique. - /// - public bool UniqueItems { get; set; } - - /// - /// Reads a from the specified . - /// - /// The containing the JSON Schema to read. - /// The object representing the JSON Schema. - public static JsonSchema Read(JsonReader reader) => Read(reader, new JsonSchemaResolver()); - - /// - /// Reads a from the specified . - /// - /// The containing the JSON Schema to read. - /// The to use when resolving schema references. - /// The object representing the JSON Schema. - public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - ValidationUtils.ArgumentNotNull(resolver, nameof(resolver)); - - var builder = new JsonSchemaBuilder(resolver); - return builder.Read(reader); - } - - /// - /// Load a from a string that contains JSON Schema. - /// - /// A that contains JSON Schema. - /// A populated from the string that contains JSON Schema. - public static JsonSchema Parse(string json) => Parse(json, new JsonSchemaResolver()); - - /// - /// Load a from a string that contains JSON Schema using the specified - /// . - /// - /// A that contains JSON Schema. - /// The resolver. - /// A populated from the string that contains JSON Schema. - public static JsonSchema Parse(string json, JsonSchemaResolver resolver) - { - ValidationUtils.ArgumentNotNull(json, nameof(json)); - - using (JsonReader reader = new JsonTextReader(new StringReader(json))) return Read(reader, resolver); - } - - /// - /// Writes this schema to a . - /// - /// A into which this method will write. - public void WriteTo(JsonWriter writer) => WriteTo(writer, new JsonSchemaResolver()); - - /// - /// Writes this schema to a using the specified . - /// - /// A into which this method will write. - /// The resolver used. - public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver) - { - ValidationUtils.ArgumentNotNull(writer, nameof(writer)); - ValidationUtils.ArgumentNotNull(resolver, nameof(resolver)); - - var schemaWriter = new JsonSchemaWriter(writer, resolver); - schemaWriter.WriteSchema(this); - } - - /// - /// Returns a that represents the current . - /// - /// - /// A that represents the current . - /// - public override string ToString() - { - var writer = new StringWriter(CultureInfo.InvariantCulture); - var jsonWriter = new JsonTextWriter(writer); - jsonWriter.Formatting = Formatting.Indented; - - WriteTo(jsonWriter); - - return writer.ToString(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs deleted file mode 100644 index da291e0ed..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs +++ /dev/null @@ -1,415 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaBuilder - { - private readonly IDictionary _documentSchemas; - private readonly JsonSchemaResolver _resolver; - private readonly IList _stack; - - public JsonSchemaBuilder(JsonSchemaResolver resolver) - { - _stack = new List(); - _documentSchemas = new Dictionary(); - _resolver = resolver; - } - - private JObject _rootSchema; - - private JsonSchema CurrentSchema { get; set; } - - private void Push(JsonSchema value) - { - CurrentSchema = value; - _stack.Add(value); - _resolver.LoadedSchemas.Add(value); - _documentSchemas.Add(value.Location, value); - } - - private JsonSchema Pop() - { - var poppedSchema = CurrentSchema; - _stack.RemoveAt(_stack.Count - 1); - CurrentSchema = _stack.LastOrDefault(); - - return poppedSchema; - } - - internal JsonSchema Read(JsonReader reader) - { - var schemaToken = JToken.ReadFrom(reader); - - _rootSchema = schemaToken as JObject; - - var schema = BuildSchema(schemaToken); - - ResolveReferences(schema); - - return schema; - } - - private string UnescapeReference(string reference) => Uri.UnescapeDataString(reference).Replace("~1", "/").Replace("~0", "~"); - - private JsonSchema ResolveReferences(JsonSchema schema) - { - if (schema.DeferredReference != null) - { - var reference = schema.DeferredReference; - - var locationReference = reference.StartsWith("#", StringComparison.Ordinal); - if (locationReference) reference = UnescapeReference(reference); - - var resolvedSchema = _resolver.GetSchema(reference); - - if (resolvedSchema == null) - { - if (locationReference) - { - var escapedParts = schema.DeferredReference.TrimStart('#').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - JToken currentToken = _rootSchema; - foreach (var escapedPart in escapedParts) - { - var part = UnescapeReference(escapedPart); - - if (currentToken.Type == JTokenType.Object) - currentToken = currentToken[part]; - else if (currentToken.Type == JTokenType.Array || currentToken.Type == JTokenType.Constructor) - { - if (int.TryParse(part, out var index) && index >= 0 && index < currentToken.Count()) - currentToken = currentToken[index]; - else - currentToken = null; - } - - if (currentToken == null) break; - } - - if (currentToken != null) resolvedSchema = BuildSchema(currentToken); - } - - if (resolvedSchema == null) - throw new JsonException( - "Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, schema.DeferredReference)); - } - - schema = resolvedSchema; - } - - if (schema.ReferencesResolved) return schema; - - schema.ReferencesResolved = true; - - if (schema.Extends != null) - { - for (var i = 0; i < schema.Extends.Count; i++) schema.Extends[i] = ResolveReferences(schema.Extends[i]); - } - - if (schema.Items != null) - { - for (var i = 0; i < schema.Items.Count; i++) schema.Items[i] = ResolveReferences(schema.Items[i]); - } - - if (schema.AdditionalItems != null) schema.AdditionalItems = ResolveReferences(schema.AdditionalItems); - - if (schema.PatternProperties != null) - { - foreach (var patternProperty in schema.PatternProperties.ToList()) - schema.PatternProperties[patternProperty.Key] = ResolveReferences(patternProperty.Value); - } - - if (schema.Properties != null) - { - foreach (var property in schema.Properties.ToList()) schema.Properties[property.Key] = ResolveReferences(property.Value); - } - - if (schema.AdditionalProperties != null) schema.AdditionalProperties = ResolveReferences(schema.AdditionalProperties); - - return schema; - } - - private JsonSchema BuildSchema(JToken token) - { - if (!(token is JObject schemaObject)) - throw JsonException.Create(token, token.Path, - "Expected object while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - if (schemaObject.TryGetValue(JsonTypeReflector.RefPropertyName, out var referenceToken)) - { - var deferredSchema = new JsonSchema(); - deferredSchema.DeferredReference = (string)referenceToken; - - return deferredSchema; - } - - var location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty); - if (!StringUtils.IsNullOrEmpty(location)) location = "/" + location; - location = "#" + location; - - if (_documentSchemas.TryGetValue(location, out var existingSchema)) return existingSchema; - - Push(new JsonSchema { Location = location }); - - ProcessSchemaProperties(schemaObject); - - return Pop(); - } - - private void ProcessSchemaProperties(JObject schemaObject) - { - foreach (var property in schemaObject) - { - switch (property.Key) - { - case JsonSchemaConstants.TypePropertyName: - CurrentSchema.Type = ProcessType(property.Value); - break; - case JsonSchemaConstants.IdPropertyName: - CurrentSchema.Id = (string)property.Value; - break; - case JsonSchemaConstants.TitlePropertyName: - CurrentSchema.Title = (string)property.Value; - break; - case JsonSchemaConstants.DescriptionPropertyName: - CurrentSchema.Description = (string)property.Value; - break; - case JsonSchemaConstants.PropertiesPropertyName: - CurrentSchema.Properties = ProcessProperties(property.Value); - break; - case JsonSchemaConstants.ItemsPropertyName: - ProcessItems(property.Value); - break; - case JsonSchemaConstants.AdditionalPropertiesPropertyName: - ProcessAdditionalProperties(property.Value); - break; - case JsonSchemaConstants.AdditionalItemsPropertyName: - ProcessAdditionalItems(property.Value); - break; - case JsonSchemaConstants.PatternPropertiesPropertyName: - CurrentSchema.PatternProperties = ProcessProperties(property.Value); - break; - case JsonSchemaConstants.RequiredPropertyName: - CurrentSchema.Required = (bool)property.Value; - break; - case JsonSchemaConstants.RequiresPropertyName: - CurrentSchema.Requires = (string)property.Value; - break; - case JsonSchemaConstants.MinimumPropertyName: - CurrentSchema.Minimum = (double)property.Value; - break; - case JsonSchemaConstants.MaximumPropertyName: - CurrentSchema.Maximum = (double)property.Value; - break; - case JsonSchemaConstants.ExclusiveMinimumPropertyName: - CurrentSchema.ExclusiveMinimum = (bool)property.Value; - break; - case JsonSchemaConstants.ExclusiveMaximumPropertyName: - CurrentSchema.ExclusiveMaximum = (bool)property.Value; - break; - case JsonSchemaConstants.MaximumLengthPropertyName: - CurrentSchema.MaximumLength = (int)property.Value; - break; - case JsonSchemaConstants.MinimumLengthPropertyName: - CurrentSchema.MinimumLength = (int)property.Value; - break; - case JsonSchemaConstants.MaximumItemsPropertyName: - CurrentSchema.MaximumItems = (int)property.Value; - break; - case JsonSchemaConstants.MinimumItemsPropertyName: - CurrentSchema.MinimumItems = (int)property.Value; - break; - case JsonSchemaConstants.DivisibleByPropertyName: - CurrentSchema.DivisibleBy = (double)property.Value; - break; - case JsonSchemaConstants.DisallowPropertyName: - CurrentSchema.Disallow = ProcessType(property.Value); - break; - case JsonSchemaConstants.DefaultPropertyName: - CurrentSchema.Default = property.Value.DeepClone(); - break; - case JsonSchemaConstants.HiddenPropertyName: - CurrentSchema.Hidden = (bool)property.Value; - break; - case JsonSchemaConstants.ReadOnlyPropertyName: - CurrentSchema.ReadOnly = (bool)property.Value; - break; - case JsonSchemaConstants.FormatPropertyName: - CurrentSchema.Format = (string)property.Value; - break; - case JsonSchemaConstants.PatternPropertyName: - CurrentSchema.Pattern = (string)property.Value; - break; - case JsonSchemaConstants.EnumPropertyName: - ProcessEnum(property.Value); - break; - case JsonSchemaConstants.ExtendsPropertyName: - ProcessExtends(property.Value); - break; - case JsonSchemaConstants.UniqueItemsPropertyName: - CurrentSchema.UniqueItems = (bool)property.Value; - break; - } - } - } - - private void ProcessExtends(JToken token) - { - IList schemas = new List(); - - if (token.Type == JTokenType.Array) - { - foreach (var schemaObject in token) schemas.Add(BuildSchema(schemaObject)); - } - else - { - var schema = BuildSchema(token); - if (schema != null) schemas.Add(schema); - } - - if (schemas.Count > 0) CurrentSchema.Extends = schemas; - } - - private void ProcessEnum(JToken token) - { - if (token.Type != JTokenType.Array) - throw JsonException.Create(token, token.Path, - "Expected Array token while parsing enum values, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - CurrentSchema.Enum = new List(); - - foreach (var enumValue in token) CurrentSchema.Enum.Add(enumValue.DeepClone()); - } - - private void ProcessAdditionalProperties(JToken token) - { - if (token.Type == JTokenType.Boolean) - CurrentSchema.AllowAdditionalProperties = (bool)token; - else - CurrentSchema.AdditionalProperties = BuildSchema(token); - } - - private void ProcessAdditionalItems(JToken token) - { - if (token.Type == JTokenType.Boolean) - CurrentSchema.AllowAdditionalItems = (bool)token; - else - CurrentSchema.AdditionalItems = BuildSchema(token); - } - - private IDictionary ProcessProperties(JToken token) - { - IDictionary properties = new Dictionary(); - - if (token.Type != JTokenType.Object) - throw JsonException.Create(token, token.Path, - "Expected Object token while parsing schema properties, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - foreach (JProperty propertyToken in token) - { - if (properties.ContainsKey(propertyToken.Name)) - throw new JsonException( - "Property {0} has already been defined in schema.".FormatWith(CultureInfo.InvariantCulture, propertyToken.Name)); - - properties.Add(propertyToken.Name, BuildSchema(propertyToken.Value)); - } - - return properties; - } - - private void ProcessItems(JToken token) - { - CurrentSchema.Items = new List(); - - switch (token.Type) - { - case JTokenType.Object: - CurrentSchema.Items.Add(BuildSchema(token)); - CurrentSchema.PositionalItemsValidation = false; - break; - case JTokenType.Array: - CurrentSchema.PositionalItemsValidation = true; - foreach (var schemaToken in token) CurrentSchema.Items.Add(BuildSchema(schemaToken)); - break; - default: - throw JsonException.Create(token, token.Path, - "Expected array or JSON schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - } - } - - private JsonSchemaType? ProcessType(JToken token) - { - switch (token.Type) - { - case JTokenType.Array: - // ensure type is in blank state before ORing values - JsonSchemaType? type = JsonSchemaType.None; - - foreach (var typeToken in token) - { - if (typeToken.Type != JTokenType.String) - throw JsonException.Create(typeToken, typeToken.Path, - "Expected JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - - type = type | MapType((string)typeToken); - } - - return type; - case JTokenType.String: - return MapType((string)token); - default: - throw JsonException.Create(token, token.Path, - "Expected array or JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); - } - } - - internal static JsonSchemaType MapType(string type) - { - if (!JsonSchemaConstants.JsonSchemaTypeMapping.TryGetValue(type, out var mappedType)) - throw new JsonException("Invalid JSON schema type: {0}".FormatWith(CultureInfo.InvariantCulture, type)); - - return mappedType; - } - - internal static string MapType(JsonSchemaType type) => JsonSchemaConstants.JsonSchemaTypeMapping.Single(kv => kv.Value == type).Key; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaConstants.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaConstants.cs deleted file mode 100644 index 48dfc6d8f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaConstants.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal static class JsonSchemaConstants - { - public const string AdditionalItemsPropertyName = "additionalItems"; - public const string AdditionalPropertiesPropertyName = "additionalProperties"; - public const string DefaultPropertyName = "default"; - public const string DescriptionPropertyName = "description"; - public const string DisallowPropertyName = "disallow"; - public const string DivisibleByPropertyName = "divisibleBy"; - public const string EnumPropertyName = "enum"; - public const string ExclusiveMaximumPropertyName = "exclusiveMaximum"; - public const string ExclusiveMinimumPropertyName = "exclusiveMinimum"; - public const string ExtendsPropertyName = "extends"; - public const string FormatPropertyName = "format"; - public const string HiddenPropertyName = "hidden"; - public const string IdPropertyName = "id"; - public const string ItemsPropertyName = "items"; - public const string MaximumItemsPropertyName = "maxItems"; - public const string MaximumLengthPropertyName = "maxLength"; - public const string MaximumPropertyName = "maximum"; - public const string MinimumItemsPropertyName = "minItems"; - public const string MinimumLengthPropertyName = "minLength"; - public const string MinimumPropertyName = "minimum"; - public const string OptionLabelPropertyName = "label"; - - public const string OptionValuePropertyName = "value"; - public const string PatternPropertiesPropertyName = "patternProperties"; - public const string PatternPropertyName = "pattern"; - public const string PropertiesPropertyName = "properties"; - public const string ReadOnlyPropertyName = "readonly"; - public const string RequiredPropertyName = "required"; - public const string RequiresPropertyName = "requires"; - public const string TitlePropertyName = "title"; - public const string TransientPropertyName = "transient"; - public const string TypePropertyName = "type"; - public const string UniqueItemsPropertyName = "uniqueItems"; - - public static readonly IDictionary JsonSchemaTypeMapping = new Dictionary - { - { "string", JsonSchemaType.String }, - { "object", JsonSchemaType.Object }, - { "integer", JsonSchemaType.Integer }, - { "number", JsonSchemaType.Float }, - { "null", JsonSchemaType.Null }, - { "boolean", JsonSchemaType.Boolean }, - { "array", JsonSchemaType.Array }, - { "any", JsonSchemaType.Any } - }; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaException.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaException.cs deleted file mode 100644 index 851041dbd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaException.cs +++ /dev/null @@ -1,115 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Returns detailed information about the schema exception. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - [Serializable] -#endif - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaException : JsonException - { - /// - /// Gets the line number indicating where the error occurred. - /// - /// The line number indicating where the error occurred. - public int LineNumber { get; } - - /// - /// Gets the line position indicating where the error occurred. - /// - /// The line position indicating where the error occurred. - public int LinePosition { get; } - - /// - /// Gets the path to the JSON where the error occurred. - /// - /// The path to the JSON where the error occurred. - public string Path { get; } - - /// - /// Initializes a new instance of the class. - /// - public JsonSchemaException() { } - - /// - /// Initializes a new instance of the class - /// with a specified error message. - /// - /// The error message that explains the reason for the exception. - public JsonSchemaException(string message) - : base(message) { } - - /// - /// Initializes a new instance of the class - /// with a specified error message and a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// - /// The exception that is the cause of the current exception, or null if no inner - /// exception is specified. - /// - public JsonSchemaException(string message, Exception innerException) - : base(message, innerException) { } - -#if HAVE_BINARY_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - /// The parameter is null. - /// The class name is null or is zero (0). - public JsonSchemaException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } -#endif - - internal JsonSchemaException(string message, Exception innerException, string path, int lineNumber, int linePosition) - : base(message, innerException) - { - Path = path; - LineNumber = lineNumber; - LinePosition = linePosition; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs deleted file mode 100644 index 3b77edfbd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ /dev/null @@ -1,442 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Generates a from a specified . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaGenerator - { - /// - /// Gets or sets how undefined schemas are handled by the serializer. - /// - public UndefinedSchemaIdHandling UndefinedSchemaIdHandling { get; set; } - - private IContractResolver _contractResolver; - - /// - /// Gets or sets the contract resolver. - /// - /// The contract resolver. - public IContractResolver ContractResolver - { - get - { - if (_contractResolver == null) return DefaultContractResolver.Instance; - - return _contractResolver; - } - set => _contractResolver = value; - } - - private class TypeSchema - { - public TypeSchema(Type type, JsonSchema schema) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - ValidationUtils.ArgumentNotNull(schema, nameof(schema)); - - Type = type; - Schema = schema; - } - - public JsonSchema Schema { get; } - public Type Type { get; } - } - - private JsonSchemaResolver _resolver; - private readonly IList _stack = new List(); - - private JsonSchema CurrentSchema { get; set; } - - private void Push(TypeSchema typeSchema) - { - CurrentSchema = typeSchema.Schema; - _stack.Add(typeSchema); - _resolver.LoadedSchemas.Add(typeSchema.Schema); - } - - private TypeSchema Pop() - { - var popped = _stack[_stack.Count - 1]; - _stack.RemoveAt(_stack.Count - 1); - var newValue = _stack.LastOrDefault(); - if (newValue != null) - CurrentSchema = newValue.Schema; - else - CurrentSchema = null; - - return popped; - } - - /// - /// Generate a from the specified type. - /// - /// The type to generate a from. - /// A generated from the specified type. - public JsonSchema Generate(Type type) => Generate(type, new JsonSchemaResolver(), false); - - /// - /// Generate a from the specified type. - /// - /// The type to generate a from. - /// The used to resolve schema references. - /// A generated from the specified type. - public JsonSchema Generate(Type type, JsonSchemaResolver resolver) => Generate(type, resolver, false); - - /// - /// Generate a from the specified type. - /// - /// The type to generate a from. - /// Specify whether the generated root will be nullable. - /// A generated from the specified type. - public JsonSchema Generate(Type type, bool rootSchemaNullable) => Generate(type, new JsonSchemaResolver(), rootSchemaNullable); - - /// - /// Generate a from the specified type. - /// - /// The type to generate a from. - /// The used to resolve schema references. - /// Specify whether the generated root will be nullable. - /// A generated from the specified type. - public JsonSchema Generate(Type type, JsonSchemaResolver resolver, bool rootSchemaNullable) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - ValidationUtils.ArgumentNotNull(resolver, nameof(resolver)); - - _resolver = resolver; - - return GenerateInternal(type, !rootSchemaNullable ? Required.Always : Required.Default, false); - } - - private string GetTitle(Type type) - { - var containerAttribute = JsonTypeReflector.GetCachedAttribute(type); - - if (!StringUtils.IsNullOrEmpty(containerAttribute?.Title)) return containerAttribute.Title; - - return null; - } - - private string GetDescription(Type type) - { - var containerAttribute = JsonTypeReflector.GetCachedAttribute(type); - - if (!StringUtils.IsNullOrEmpty(containerAttribute?.Description)) return containerAttribute.Description; - -#if HAVE_ADO_NET - DescriptionAttribute descriptionAttribute = ReflectionUtils.GetAttribute(type); - return descriptionAttribute?.Description; -#else - return null; -#endif - } - - private string GetTypeId(Type type, bool explicitOnly) - { - var containerAttribute = JsonTypeReflector.GetCachedAttribute(type); - - if (!StringUtils.IsNullOrEmpty(containerAttribute?.Id)) return containerAttribute.Id; - - if (explicitOnly) return null; - - switch (UndefinedSchemaIdHandling) - { - case UndefinedSchemaIdHandling.UseTypeName: - return type.FullName; - case UndefinedSchemaIdHandling.UseAssemblyQualifiedName: - return type.AssemblyQualifiedName; - default: - return null; - } - } - - private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - - var resolvedId = GetTypeId(type, false); - var explicitId = GetTypeId(type, true); - - if (!StringUtils.IsNullOrEmpty(resolvedId)) - { - var resolvedSchema = _resolver.GetSchema(resolvedId); - if (resolvedSchema != null) - { - // resolved schema is not null but referencing member allows nulls - // change resolved schema to allow nulls. hacky but what are ya gonna do? - if (valueRequired != Required.Always && !HasFlag(resolvedSchema.Type, JsonSchemaType.Null)) - resolvedSchema.Type |= JsonSchemaType.Null; - if (required && resolvedSchema.Required != true) resolvedSchema.Required = true; - - return resolvedSchema; - } - } - - // test for unresolved circular reference - if (_stack.Any(tc => tc.Type == type)) - throw new JsonException( - "Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property." - .FormatWith(CultureInfo.InvariantCulture, type)); - - var contract = ContractResolver.ResolveContract(type); - var converter = contract.Converter ?? contract.InternalConverter; - - Push(new TypeSchema(type, new JsonSchema())); - - if (explicitId != null) CurrentSchema.Id = explicitId; - - if (required) CurrentSchema.Required = true; - CurrentSchema.Title = GetTitle(type); - CurrentSchema.Description = GetDescription(type); - - if (converter != null) - { - // todo: Add GetSchema to JsonConverter and use here? - CurrentSchema.Type = JsonSchemaType.Any; - } - else - { - switch (contract.ContractType) - { - case JsonContractType.Object: - CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); - CurrentSchema.Id = GetTypeId(type, false); - GenerateObjectSchema(type, (JsonObjectContract)contract); - break; - case JsonContractType.Array: - CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired); - - CurrentSchema.Id = GetTypeId(type, false); - - var arrayAttribute = JsonTypeReflector.GetCachedAttribute(type); - var allowNullItem = arrayAttribute == null || arrayAttribute.AllowNullItems; - - var collectionItemType = ReflectionUtils.GetCollectionItemType(type); - if (collectionItemType != null) - { - CurrentSchema.Items = new List(); - CurrentSchema.Items.Add(GenerateInternal(collectionItemType, !allowNullItem ? Required.Always : Required.Default, false)); - } - break; - case JsonContractType.Primitive: - CurrentSchema.Type = GetJsonSchemaType(type, valueRequired); - - if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum() && !type.IsDefined(typeof(FlagsAttribute), true)) - { - CurrentSchema.Enum = new List(); - - var enumValues = EnumUtils.GetEnumValuesAndNames(type); - for (var i = 0; i < enumValues.Names.Length; i++) - { - var v = enumValues.Values[i]; - var value = JToken.FromObject(Enum.ToObject(type, v)); - - CurrentSchema.Enum.Add(value); - } - } - break; - case JsonContractType.String: - var schemaType = !ReflectionUtils.IsNullable(contract.UnderlyingType) - ? JsonSchemaType.String - : AddNullType(JsonSchemaType.String, valueRequired); - - CurrentSchema.Type = schemaType; - break; - case JsonContractType.Dictionary: - CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); - - Type keyType; - Type valueType; - ReflectionUtils.GetDictionaryKeyValueTypes(type, out keyType, out valueType); - - if (keyType != null) - { - var keyContract = ContractResolver.ResolveContract(keyType); - - // can be converted to a string - if (keyContract.ContractType == JsonContractType.Primitive) - CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false); - } - break; -#if HAVE_BINARY_SERIALIZATION - case JsonContractType.Serializable: - CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); - CurrentSchema.Id = GetTypeId(type, false); - GenerateISerializableContract(type, (JsonISerializableContract)contract); - break; -#endif -#if HAVE_DYNAMIC - case JsonContractType.Dynamic: -#endif - case JsonContractType.Linq: - CurrentSchema.Type = JsonSchemaType.Any; - break; - default: - throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract)); - } - } - - return Pop().Schema; - } - - private JsonSchemaType AddNullType(JsonSchemaType type, Required valueRequired) - { - if (valueRequired != Required.Always) return type | JsonSchemaType.Null; - - return type; - } - - private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) => (value & flag) == flag; - - private void GenerateObjectSchema(Type type, JsonObjectContract contract) - { - CurrentSchema.Properties = new Dictionary(); - foreach (var property in contract.Properties) - { - if (!property.Ignored) - { - var optional = property.NullValueHandling == NullValueHandling.Ignore || - HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) || - property.ShouldSerialize != null || - property.GetIsSpecified != null; - - var propertySchema = GenerateInternal(property.PropertyType, property.Required, !optional); - - if (property.DefaultValue != null) propertySchema.Default = JToken.FromObject(property.DefaultValue); - - CurrentSchema.Properties.Add(property.PropertyName, propertySchema); - } - } - - if (type.IsSealed()) CurrentSchema.AllowAdditionalProperties = false; - } - -#if HAVE_BINARY_SERIALIZATION - private void GenerateISerializableContract(Type type, JsonISerializableContract contract) - { - CurrentSchema.AllowAdditionalProperties = true; - } -#endif - - internal static bool HasFlag(JsonSchemaType? value, JsonSchemaType flag) - { - // default value is Any - if (value == null) return true; - - var match = (value & flag) == flag; - if (match) return true; - - // integer is a subset of float - if (flag == JsonSchemaType.Integer && (value & JsonSchemaType.Float) == JsonSchemaType.Float) return true; - - return false; - } - - private JsonSchemaType GetJsonSchemaType(Type type, Required valueRequired) - { - var schemaType = JsonSchemaType.None; - if (valueRequired != Required.Always && ReflectionUtils.IsNullable(type)) - { - schemaType = JsonSchemaType.Null; - if (ReflectionUtils.IsNullableType(type)) type = Nullable.GetUnderlyingType(type); - } - - var typeCode = ConvertUtils.GetTypeCode(type); - - switch (typeCode) - { - case PrimitiveTypeCode.Empty: - case PrimitiveTypeCode.Object: - return schemaType | JsonSchemaType.String; -#if HAVE_DB_NULL_TYPE_CODE - case PrimitiveTypeCode.DBNull: - return schemaType | JsonSchemaType.Null; -#endif - case PrimitiveTypeCode.Boolean: - return schemaType | JsonSchemaType.Boolean; - case PrimitiveTypeCode.Char: - return schemaType | JsonSchemaType.String; - case PrimitiveTypeCode.SByte: - case PrimitiveTypeCode.Byte: - case PrimitiveTypeCode.Int16: - case PrimitiveTypeCode.UInt16: - case PrimitiveTypeCode.Int32: - case PrimitiveTypeCode.UInt32: - case PrimitiveTypeCode.Int64: - case PrimitiveTypeCode.UInt64: -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigInteger: -#endif - return schemaType | JsonSchemaType.Integer; - case PrimitiveTypeCode.Single: - case PrimitiveTypeCode.Double: - case PrimitiveTypeCode.Decimal: - return schemaType | JsonSchemaType.Float; - // convert to string? - case PrimitiveTypeCode.DateTime: -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: -#endif - return schemaType | JsonSchemaType.String; - case PrimitiveTypeCode.String: - case PrimitiveTypeCode.Uri: - case PrimitiveTypeCode.Guid: - case PrimitiveTypeCode.TimeSpan: - case PrimitiveTypeCode.Bytes: - return schemaType | JsonSchemaType.String; - default: - throw new JsonException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type)); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModel.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModel.cs deleted file mode 100644 index 3c8692324..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModel.cs +++ /dev/null @@ -1,120 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaModel - { - public JsonSchemaModel() - { - Type = JsonSchemaType.Any; - AllowAdditionalProperties = true; - AllowAdditionalItems = true; - Required = false; - } - - public JsonSchemaModel AdditionalItems { get; set; } - public JsonSchemaModel AdditionalProperties { get; set; } - public bool AllowAdditionalItems { get; set; } - public bool AllowAdditionalProperties { get; set; } - public JsonSchemaType Disallow { get; set; } - public double? DivisibleBy { get; set; } - public IList Enum { get; set; } - public bool ExclusiveMaximum { get; set; } - public bool ExclusiveMinimum { get; set; } - public IList Items { get; set; } - public double? Maximum { get; set; } - public int? MaximumItems { get; set; } - public int? MaximumLength { get; set; } - public double? Minimum { get; set; } - public int? MinimumItems { get; set; } - public int? MinimumLength { get; set; } - public IDictionary PatternProperties { get; set; } - public IList Patterns { get; set; } - public bool PositionalItemsValidation { get; set; } - public IDictionary Properties { get; set; } - public bool Required { get; set; } - public JsonSchemaType Type { get; set; } - public bool UniqueItems { get; set; } - - public static JsonSchemaModel Create(IList schemata) - { - var model = new JsonSchemaModel(); - - foreach (var schema in schemata) Combine(model, schema); - - return model; - } - - private static void Combine(JsonSchemaModel model, JsonSchema schema) - { - // Version 3 of the Draft JSON Schema has the default value of Not Required - model.Required = model.Required || (schema.Required ?? false); - model.Type = model.Type & (schema.Type ?? JsonSchemaType.Any); - - model.MinimumLength = MathUtils.Max(model.MinimumLength, schema.MinimumLength); - model.MaximumLength = MathUtils.Min(model.MaximumLength, schema.MaximumLength); - - // not sure what is the best way to combine divisibleBy - model.DivisibleBy = MathUtils.Max(model.DivisibleBy, schema.DivisibleBy); - - model.Minimum = MathUtils.Max(model.Minimum, schema.Minimum); - model.Maximum = MathUtils.Max(model.Maximum, schema.Maximum); - model.ExclusiveMinimum = model.ExclusiveMinimum || (schema.ExclusiveMinimum ?? false); - model.ExclusiveMaximum = model.ExclusiveMaximum || (schema.ExclusiveMaximum ?? false); - - model.MinimumItems = MathUtils.Max(model.MinimumItems, schema.MinimumItems); - model.MaximumItems = MathUtils.Min(model.MaximumItems, schema.MaximumItems); - model.PositionalItemsValidation = model.PositionalItemsValidation || schema.PositionalItemsValidation; - model.AllowAdditionalProperties = model.AllowAdditionalProperties && schema.AllowAdditionalProperties; - model.AllowAdditionalItems = model.AllowAdditionalItems && schema.AllowAdditionalItems; - model.UniqueItems = model.UniqueItems || schema.UniqueItems; - if (schema.Enum != null) - { - if (model.Enum == null) model.Enum = new List(); - - model.Enum.AddRangeDistinct(schema.Enum, JToken.EqualityComparer); - } - model.Disallow = model.Disallow | (schema.Disallow ?? JsonSchemaType.None); - - if (schema.Pattern != null) - { - if (model.Patterns == null) model.Patterns = new List(); - - model.Patterns.AddDistinct(schema.Pattern); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs deleted file mode 100644 index 9bfee4933..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs +++ /dev/null @@ -1,167 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaModelBuilder - { - private JsonSchemaNode _node; - private Dictionary _nodeModels = new(); - private JsonSchemaNodeCollection _nodes = new(); - - public JsonSchemaModel Build(JsonSchema schema) - { - _nodes = new JsonSchemaNodeCollection(); - _node = AddSchema(null, schema); - - _nodeModels = new Dictionary(); - var model = BuildNodeModel(_node); - - return model; - } - - public JsonSchemaNode AddSchema(JsonSchemaNode existingNode, JsonSchema schema) - { - string newId; - if (existingNode != null) - { - if (existingNode.Schemas.Contains(schema)) return existingNode; - - newId = JsonSchemaNode.GetId(existingNode.Schemas.Union(new[] { schema })); - } - else - newId = JsonSchemaNode.GetId(new[] { schema }); - - if (_nodes.Contains(newId)) return _nodes[newId]; - - var currentNode = existingNode != null - ? existingNode.Combine(schema) - : new JsonSchemaNode(schema); - - _nodes.Add(currentNode); - - AddProperties(schema.Properties, currentNode.Properties); - - AddProperties(schema.PatternProperties, currentNode.PatternProperties); - - if (schema.Items != null) - { - for (var i = 0; i < schema.Items.Count; i++) AddItem(currentNode, i, schema.Items[i]); - } - - if (schema.AdditionalItems != null) AddAdditionalItems(currentNode, schema.AdditionalItems); - - if (schema.AdditionalProperties != null) AddAdditionalProperties(currentNode, schema.AdditionalProperties); - - if (schema.Extends != null) - { - foreach (var jsonSchema in schema.Extends) currentNode = AddSchema(currentNode, jsonSchema); - } - - return currentNode; - } - - public void AddProperties(IDictionary source, IDictionary target) - { - if (source != null) - { - foreach (var property in source) AddProperty(target, property.Key, property.Value); - } - } - - public void AddProperty(IDictionary target, string propertyName, JsonSchema schema) - { - target.TryGetValue(propertyName, out var propertyNode); - - target[propertyName] = AddSchema(propertyNode, schema); - } - - public void AddItem(JsonSchemaNode parentNode, int index, JsonSchema schema) - { - var existingItemNode = parentNode.Items.Count > index - ? parentNode.Items[index] - : null; - - var newItemNode = AddSchema(existingItemNode, schema); - - if (!(parentNode.Items.Count > index)) - parentNode.Items.Add(newItemNode); - else - parentNode.Items[index] = newItemNode; - } - - public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema) => - parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema); - - public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema) => - parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema); - - private JsonSchemaModel BuildNodeModel(JsonSchemaNode node) - { - if (_nodeModels.TryGetValue(node, out var model)) return model; - - model = JsonSchemaModel.Create(node.Schemas); - _nodeModels[node] = model; - - foreach (var property in node.Properties) - { - if (model.Properties == null) model.Properties = new Dictionary(); - - model.Properties[property.Key] = BuildNodeModel(property.Value); - } - foreach (var property in node.PatternProperties) - { - if (model.PatternProperties == null) model.PatternProperties = new Dictionary(); - - model.PatternProperties[property.Key] = BuildNodeModel(property.Value); - } - foreach (var t in node.Items) - { - if (model.Items == null) model.Items = new List(); - - model.Items.Add(BuildNodeModel(t)); - } - if (node.AdditionalProperties != null) model.AdditionalProperties = BuildNodeModel(node.AdditionalProperties); - if (node.AdditionalItems != null) model.AdditionalItems = BuildNodeModel(node.AdditionalItems); - - return model; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNode.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNode.cs deleted file mode 100644 index 153122f3a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNode.cs +++ /dev/null @@ -1,88 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaNode - { - public JsonSchemaNode(JsonSchema schema) - { - Schemas = new ReadOnlyCollection(new[] { schema }); - Properties = new Dictionary(); - PatternProperties = new Dictionary(); - Items = new List(); - - Id = GetId(Schemas); - } - - private JsonSchemaNode(JsonSchemaNode source, JsonSchema schema) - { - Schemas = new ReadOnlyCollection(source.Schemas.Union(new[] { schema }).ToList()); - Properties = new Dictionary(source.Properties); - PatternProperties = new Dictionary(source.PatternProperties); - Items = new List(source.Items); - AdditionalProperties = source.AdditionalProperties; - AdditionalItems = source.AdditionalItems; - - Id = GetId(Schemas); - } - - public JsonSchemaNode AdditionalItems { get; set; } - public JsonSchemaNode AdditionalProperties { get; set; } - public string Id { get; } - public List Items { get; } - public Dictionary PatternProperties { get; } - public Dictionary Properties { get; } - public ReadOnlyCollection Schemas { get; } - - public JsonSchemaNode Combine(JsonSchema schema) => new(this, schema); - - public static string GetId(IEnumerable schemata) - { - return string.Join("-", schemata.Select(s => s.InternalId) - .OrderBy(id => id, StringComparer.Ordinal) -#if !HAVE_STRING_JOIN_WITH_ENUMERABLE - .ToArray() -#endif - ); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs deleted file mode 100644 index a814146e2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.ObjectModel; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaNodeCollection : KeyedCollection - { - protected override string GetKeyForItem(JsonSchemaNode item) => item.Id; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaResolver.cs deleted file mode 100644 index 15008935f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaResolver.cs +++ /dev/null @@ -1,79 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Resolves from an id. - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaResolver - { - /// - /// Initializes a new instance of the class. - /// - public JsonSchemaResolver() => LoadedSchemas = new List(); - - /// - /// Gets or sets the loaded schemas. - /// - /// The loaded schemas. - public IList LoadedSchemas { get; protected set; } - - /// - /// Gets a for the specified reference. - /// - /// The id. - /// A for the specified reference. - public virtual JsonSchema GetSchema(string reference) - { - var schema = LoadedSchemas.SingleOrDefault(s => string.Equals(s.Id, reference, StringComparison.Ordinal)); - - if (schema == null) schema = LoadedSchemas.SingleOrDefault(s => string.Equals(s.Location, reference, StringComparison.Ordinal)); - - return schema; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaType.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaType.cs deleted file mode 100644 index f5ffa3c72..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaType.cs +++ /dev/null @@ -1,92 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// The value types allowed by the . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Flags] - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal enum JsonSchemaType - { - /// - /// No type specified. - /// - None = 0, - - /// - /// String type. - /// - String = 1, - - /// - /// Float type. - /// - Float = 2, - - /// - /// Integer type. - /// - Integer = 4, - - /// - /// Boolean type. - /// - Boolean = 8, - - /// - /// Object type. - /// - Object = 16, - - /// - /// Array type. - /// - Array = 32, - - /// - /// Null type. - /// - Null = 64, - - /// - /// Any type. - /// - Any = String | Float | Integer | Boolean | Object | Array | Null - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaWriter.cs deleted file mode 100644 index 600bea2ed..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/JsonSchemaWriter.cs +++ /dev/null @@ -1,232 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class JsonSchemaWriter - { - private readonly JsonSchemaResolver _resolver; - private readonly JsonWriter _writer; - - public JsonSchemaWriter(JsonWriter writer, JsonSchemaResolver resolver) - { - ValidationUtils.ArgumentNotNull(writer, nameof(writer)); - _writer = writer; - _resolver = resolver; - } - - private void ReferenceOrWriteSchema(JsonSchema schema) - { - if (schema.Id != null && _resolver.GetSchema(schema.Id) != null) - { - _writer.WriteStartObject(); - _writer.WritePropertyName(JsonTypeReflector.RefPropertyName); - _writer.WriteValue(schema.Id); - _writer.WriteEndObject(); - } - else - WriteSchema(schema); - } - - public void WriteSchema(JsonSchema schema) - { - ValidationUtils.ArgumentNotNull(schema, nameof(schema)); - - if (!_resolver.LoadedSchemas.Contains(schema)) _resolver.LoadedSchemas.Add(schema); - - _writer.WriteStartObject(); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.IdPropertyName, schema.Id); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.TitlePropertyName, schema.Title); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.DescriptionPropertyName, schema.Description); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.RequiredPropertyName, schema.Required); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.ReadOnlyPropertyName, schema.ReadOnly); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.HiddenPropertyName, schema.Hidden); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.TransientPropertyName, schema.Transient); - if (schema.Type != null) WriteType(JsonSchemaConstants.TypePropertyName, _writer, schema.Type.GetValueOrDefault()); - if (!schema.AllowAdditionalProperties) - { - _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName); - _writer.WriteValue(schema.AllowAdditionalProperties); - } - else - { - if (schema.AdditionalProperties != null) - { - _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName); - ReferenceOrWriteSchema(schema.AdditionalProperties); - } - } - if (!schema.AllowAdditionalItems) - { - _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName); - _writer.WriteValue(schema.AllowAdditionalItems); - } - else - { - if (schema.AdditionalItems != null) - { - _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName); - ReferenceOrWriteSchema(schema.AdditionalItems); - } - } - WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PropertiesPropertyName, schema.Properties); - WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PatternPropertiesPropertyName, schema.PatternProperties); - WriteItems(schema); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumPropertyName, schema.Minimum); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumPropertyName, schema.Maximum); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMinimumPropertyName, schema.ExclusiveMinimum); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMaximumPropertyName, schema.ExclusiveMaximum); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumLengthPropertyName, schema.MinimumLength); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumLengthPropertyName, schema.MaximumLength); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumItemsPropertyName, schema.MinimumItems); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumItemsPropertyName, schema.MaximumItems); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.DivisibleByPropertyName, schema.DivisibleBy); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.FormatPropertyName, schema.Format); - WritePropertyIfNotNull(_writer, JsonSchemaConstants.PatternPropertyName, schema.Pattern); - if (schema.Enum != null) - { - _writer.WritePropertyName(JsonSchemaConstants.EnumPropertyName); - _writer.WriteStartArray(); - foreach (var token in schema.Enum) token.WriteTo(_writer); - _writer.WriteEndArray(); - } - if (schema.Default != null) - { - _writer.WritePropertyName(JsonSchemaConstants.DefaultPropertyName); - schema.Default.WriteTo(_writer); - } - if (schema.Disallow != null) WriteType(JsonSchemaConstants.DisallowPropertyName, _writer, schema.Disallow.GetValueOrDefault()); - if (schema.Extends != null && schema.Extends.Count > 0) - { - _writer.WritePropertyName(JsonSchemaConstants.ExtendsPropertyName); - if (schema.Extends.Count == 1) - ReferenceOrWriteSchema(schema.Extends[0]); - else - { - _writer.WriteStartArray(); - foreach (var jsonSchema in schema.Extends) ReferenceOrWriteSchema(jsonSchema); - _writer.WriteEndArray(); - } - } - _writer.WriteEndObject(); - } - - private void WriteSchemaDictionaryIfNotNull(JsonWriter writer, string propertyName, IDictionary properties) - { - if (properties != null) - { - writer.WritePropertyName(propertyName); - writer.WriteStartObject(); - foreach (var property in properties) - { - writer.WritePropertyName(property.Key); - ReferenceOrWriteSchema(property.Value); - } - writer.WriteEndObject(); - } - } - - private void WriteItems(JsonSchema schema) - { - if (schema.Items == null && !schema.PositionalItemsValidation) return; - - _writer.WritePropertyName(JsonSchemaConstants.ItemsPropertyName); - - if (!schema.PositionalItemsValidation) - { - if (schema.Items != null && schema.Items.Count > 0) - ReferenceOrWriteSchema(schema.Items[0]); - else - { - _writer.WriteStartObject(); - _writer.WriteEndObject(); - } - return; - } - - _writer.WriteStartArray(); - if (schema.Items != null) - { - foreach (var itemSchema in schema.Items) ReferenceOrWriteSchema(itemSchema); - } - _writer.WriteEndArray(); - } - - private void WriteType(string propertyName, JsonWriter writer, JsonSchemaType type) - { - if (Enum.IsDefined(typeof(JsonSchemaType), type)) - { - writer.WritePropertyName(propertyName); - writer.WriteValue(JsonSchemaBuilder.MapType(type)); - } - else - { - var en = EnumUtils.GetFlagsValues(type).Where(v => v != JsonSchemaType.None).GetEnumerator(); - if (en.MoveNext()) - { - writer.WritePropertyName(propertyName); - var first = en.Current; - if (en.MoveNext()) - { - writer.WriteStartArray(); - writer.WriteValue(JsonSchemaBuilder.MapType(first)); - do - writer.WriteValue(JsonSchemaBuilder.MapType(en.Current)); - while (en.MoveNext()); - writer.WriteEndArray(); - } - else - writer.WriteValue(JsonSchemaBuilder.MapType(first)); - } - } - } - - private void WritePropertyIfNotNull(JsonWriter writer, string propertyName, object value) - { - if (value != null) - { - writer.WritePropertyName(propertyName); - writer.WriteValue(value); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs deleted file mode 100644 index 24fc3ae45..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Specifies undefined schema Id handling options for the . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal enum UndefinedSchemaIdHandling - { - /// - /// Do not infer a schema Id. - /// - None = 0, - - /// - /// Use the .NET type name as the schema Id. - /// - UseTypeName = 1, - - /// - /// Use the assembly qualified .NET type name as the schema Id. - /// - UseAssemblyQualifiedName = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventArgs.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventArgs.cs deleted file mode 100644 index b7a24b651..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventArgs.cs +++ /dev/null @@ -1,71 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Returns detailed information related to the . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal class ValidationEventArgs : EventArgs - { - internal ValidationEventArgs(JsonSchemaException ex) - { - ValidationUtils.ArgumentNotNull(ex, nameof(ex)); - Exception = ex; - } - - /// - /// Gets the associated with the validation error. - /// - /// The JsonSchemaException associated with the validation error. - public JsonSchemaException Exception { get; } - - /// - /// Gets the text description corresponding to the validation error. - /// - /// The text description. - public string Message => Exception.Message; - - /// - /// Gets the path of the JSON location where the validation error occurred. - /// - /// The path of the JSON location where the validation error occurred. - public string Path => Exception.Path; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventHandler.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventHandler.cs deleted file mode 100644 index 44515f3c4..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Schema/ValidationEventHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Schema -{ - /// - /// - /// Represents the callback method that will handle JSON schema validation events and the - /// . - /// - /// - /// JSON Schema validation has been moved to its own package. See - /// https://www.newtonsoft.com/jsonschema for more details. - /// - /// - [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] - internal delegate void ValidationEventHandler(object sender, ValidationEventArgs e); -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs deleted file mode 100644 index d82965ce1..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal static class CachedAttributeGetter where T : Attribute - { - private static readonly ThreadSafeStore TypeAttributeCache = new(JsonTypeReflector.GetAttribute); - - public static T? GetAttribute(object type) => TypeAttributeCache.Get(type); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCaseNamingStrategy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCaseNamingStrategy.cs deleted file mode 100644 index a53e30db0..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCaseNamingStrategy.cs +++ /dev/null @@ -1,83 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// A camel case naming strategy. - /// - internal class CamelCaseNamingStrategy : NamingStrategy - { - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) - { - ProcessDictionaryKeys = processDictionaryKeys; - OverrideSpecifiedNames = overrideSpecifiedNames; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - /// - /// A flag indicating whether extension data names should be processed. - /// - public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) - : this(processDictionaryKeys, overrideSpecifiedNames) => - ProcessExtensionDataNames = processExtensionDataNames; - - /// - /// Initializes a new instance of the class. - /// - public CamelCaseNamingStrategy() { } - - /// - /// Resolves the specified property name. - /// - /// The property name to resolve. - /// The resolved property name. - protected override string ResolvePropertyName(string name) => StringUtils.ToCamelCase(name); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs deleted file mode 100644 index 7214eda73..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Resolves member mappings for a type, camel casing property names. - /// - internal class CamelCasePropertyNamesContractResolver : DefaultContractResolver - { - private static Dictionary, JsonContract>? _contractCache; - private static readonly DefaultJsonNameTable NameTable = new(); - private static readonly object TypeContractCacheLock = new(); - - /// - /// Initializes a new instance of the class. - /// - public CamelCasePropertyNamesContractResolver() => - NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; - - /// - /// Resolves the contract for a given type. - /// - /// The type to resolve a contract for. - /// The contract for a given type. - public override JsonContract ResolveContract(Type type) - { - if (type == null) throw new ArgumentNullException(nameof(type)); - - // for backwards compadibility the CamelCasePropertyNamesContractResolver shares contracts between instances - var key = new StructMultiKey(GetType(), type); - var cache = _contractCache; - if (cache == null || !cache.TryGetValue(key, out var contract)) - { - contract = CreateContract(type); - - // avoid the possibility of modifying the cache dictionary while another thread is accessing it - lock (TypeContractCacheLock) - { - cache = _contractCache; - var updatedCache = cache != null - ? new Dictionary, JsonContract>(cache) - : new Dictionary, JsonContract>(); - updatedCache[key] = contract; - - _contractCache = updatedCache; - } - } - - return contract; - } - - internal override DefaultJsonNameTable GetNameTable() => NameTable; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultContractResolver.cs deleted file mode 100644 index 39fd468cd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ /dev/null @@ -1,1544 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_CONCURRENT_DICTIONARY -#endif -#if HAVE_DYNAMIC -using System.Dynamic; -#endif -#if HAVE_CAS -using System.Security.Permissions; -#endif -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Converters; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable enable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Used by to resolve a for a given . - /// - internal class DefaultContractResolver : IContractResolver - { - // Json.NET Schema requires a property - internal static IContractResolver Instance { get; } = new DefaultContractResolver(); - - private static readonly string[] BlacklistedTypeNames = { "System.IO.DriveInfo", "System.IO.FileInfo", "System.IO.DirectoryInfo" }; - - private static readonly JsonConverter[] BuiltInConverters = - { -#if HAVE_ENTITY_FRAMEWORK - new EntityKeyMemberConverter(), -#endif -#if HAVE_DYNAMIC - new ExpandoObjectConverter(), -#endif -#if (HAVE_XML_DOCUMENT || HAVE_XLINQ) - new XmlNodeConverter(), -#endif -#if HAVE_ADO_NET - new BinaryConverter(), - new DataSetConverter(), - new DataTableConverter(), -#endif -#if HAVE_FSHARP_TYPES - new DiscriminatedUnionConverter(), -#endif - new KeyValuePairConverter(), -#pragma warning disable 618 - new BsonObjectIdConverter(), -#pragma warning restore 618 - }; - - private readonly DefaultJsonNameTable _nameTable = new(); - - private readonly ThreadSafeStore _contractCache; - - /// - /// Gets a value indicating whether members are being get and set using dynamic code generation. - /// This value is determined by the runtime permissions available. - /// - /// - /// true if using dynamic code generation; otherwise, false. - /// - public bool DynamicCodeGeneration => JsonTypeReflector.DynamicCodeGeneration; - -#if !PORTABLE - /// - /// Gets or sets the default members search flags. - /// - /// The default members search flags. - [Obsolete( - "DefaultMembersSearchFlags is obsolete. To modify the members serialized inherit from DefaultContractResolver and override the GetSerializableMembers method instead.")] - public BindingFlags DefaultMembersSearchFlags { get; set; } -#else - private readonly BindingFlags DefaultMembersSearchFlags; -#endif - - /// - /// Gets or sets a value indicating whether compiler generated members should be serialized. - /// - /// - /// true if serialized compiler generated members; otherwise, false. - /// - public bool SerializeCompilerGeneratedMembers { get; set; } - -#if HAVE_BINARY_SERIALIZATION - /// - /// Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types. - /// - /// - /// true if the interface will be ignored when serializing and deserializing types; otherwise, false. - /// - public bool IgnoreSerializableInterface { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types. - /// - /// - /// true if the attribute will be ignored when serializing and deserializing types; otherwise, false. - /// - public bool IgnoreSerializableAttribute { get; set; } -#endif - - /// - /// Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types. - /// - /// - /// true if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, - /// false. - /// - public bool IgnoreIsSpecifiedMembers { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types. - /// - /// - /// true if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, - /// false. - /// - public bool IgnoreShouldSerializeMembers { get; set; } - - /// - /// Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized. - /// - /// The naming strategy used to resolve how property names and dictionary keys are serialized. - public NamingStrategy? NamingStrategy { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public DefaultContractResolver() - { -#if HAVE_BINARY_SERIALIZATION - IgnoreSerializableAttribute = true; -#endif - -#pragma warning disable 618 - DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public; -#pragma warning restore 618 - - _contractCache = new ThreadSafeStore(CreateContract); - } - - /// - /// Resolves the contract for a given type. - /// - /// The type to resolve a contract for. - /// The contract for a given type. - public virtual JsonContract ResolveContract(Type type) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - - return _contractCache.Get(type); - } - - private static bool FilterMembers(MemberInfo member) - { - if (member is PropertyInfo property) - { - if (ReflectionUtils.IsIndexedProperty(property)) return false; - - return !ReflectionUtils.IsByRefLikeType(property.PropertyType); - } - if (member is FieldInfo field) return !ReflectionUtils.IsByRefLikeType(field.FieldType); - - return true; - } - - /// - /// Gets the serializable members for the type. - /// - /// The type to get serializable members for. - /// The serializable members for the type. - protected virtual List GetSerializableMembers(Type objectType) - { - bool ignoreSerializableAttribute; -#if HAVE_BINARY_SERIALIZATION - ignoreSerializableAttribute = IgnoreSerializableAttribute; -#else - ignoreSerializableAttribute = true; -#endif - - var memberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute); - - // Exclude index properties - // Do not filter ByRef types here because accessing FieldType/PropertyType can trigger additonal assembly loads - var allMembers = ReflectionUtils - .GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - .Where(m => m is PropertyInfo p ? !ReflectionUtils.IsIndexedProperty(p) : true); - - var serializableMembers = new List(); - - if (memberSerialization != MemberSerialization.Fields) - { -#if HAVE_DATA_CONTRACTS - DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); -#endif - -#pragma warning disable 618 - // Exclude index properties and ByRef types - var defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags) - .Where(FilterMembers) - .ToList(); -#pragma warning restore 618 - - foreach (var member in allMembers) - { - // exclude members that are compiler generated if set - if (SerializeCompilerGeneratedMembers || !member.IsDefined(typeof(CompilerGeneratedAttribute), true)) - { - if (defaultMembers.Contains(member)) - { - // add all members that are found by default member search - serializableMembers.Add(member); - } - else - { - // add members that are explicitly marked with JsonProperty/DataMember attribute - // or are a field if serializing just fields - if (JsonTypeReflector.GetAttribute(member) != null) - serializableMembers.Add(member); - else if (JsonTypeReflector.GetAttribute(member) != null) - serializableMembers.Add(member); -#if HAVE_DATA_CONTRACTS - else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute(member) != null) - { - serializableMembers.Add(member); - } -#endif - else if (memberSerialization == MemberSerialization.Fields && member.MemberType() == MemberTypes.Field) - serializableMembers.Add(member); - } - } - } - -#if HAVE_DATA_CONTRACTS - // don't include EntityKey on entities objects... this is a bit hacky - if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", false, out _)) - { - serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).ToList(); - } -#endif - // don't include TargetSite on non-serializable exceptions - // MemberBase is problematic to serialize. Large, self referencing instances, etc - if (typeof(Exception).IsAssignableFrom(objectType)) - serializableMembers = serializableMembers.Where(m => !string.Equals(m.Name, "TargetSite", StringComparison.Ordinal)).ToList(); - } - else - { - // serialize all fields - foreach (var member in allMembers) - if (member is FieldInfo field && !field.IsStatic) - serializableMembers.Add(member); - } - - return serializableMembers; - } - -#if HAVE_DATA_CONTRACTS - private bool ShouldSerializeEntityMember(MemberInfo memberInfo) - { - if (memberInfo is PropertyInfo propertyInfo) - { - if (propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1") - { - return false; - } - } - - return true; - } -#endif - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonObjectContract CreateObjectContract(Type objectType) - { - var contract = new JsonObjectContract(objectType); - InitializeContract(contract); - - bool ignoreSerializableAttribute; -#if HAVE_BINARY_SERIALIZATION - ignoreSerializableAttribute = IgnoreSerializableAttribute; -#else - ignoreSerializableAttribute = true; -#endif - - contract.MemberSerialization = - JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute); - contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization)); - - Func? extensionDataNameResolver = null; - - var attribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); - if (attribute != null) - { - contract.ItemRequired = attribute._itemRequired; - contract.ItemNullValueHandling = attribute._itemNullValueHandling; - contract.MissingMemberHandling = attribute._missingMemberHandling; - - if (attribute.NamingStrategyType != null) - { - var namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute)!; - extensionDataNameResolver = s => namingStrategy.GetDictionaryKey(s); - } - } - - if (extensionDataNameResolver == null) extensionDataNameResolver = ResolveExtensionDataName; - - contract.ExtensionDataNameResolver = extensionDataNameResolver; - - if (contract.IsInstantiable) - { - var overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); - - // check if a JsonConstructorAttribute has been defined and use that - if (overrideConstructor != null) - { - contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor); - contract.CreatorParameters.AddRange(CreateConstructorParameters(overrideConstructor, contract.Properties)); - } - else if (contract.MemberSerialization == MemberSerialization.Fields) - { -#if HAVE_BINARY_FORMATTER - // mimic DataContractSerializer behaviour when populating fields by overriding default creator to create an uninitialized object - // note that this is only possible when the application is fully trusted so fall back to using the default constructor (if available) in partial trust - if (JsonTypeReflector.FullyTrusted) - { - contract.DefaultCreator = contract.GetUninitializedObject; - } -#endif - } - else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic) - { - var constructor = GetParameterizedConstructor(contract.NonNullableUnderlyingType); - if (constructor != null) - { - contract.ParameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); - contract.CreatorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties)); - } - } - else if (contract.NonNullableUnderlyingType.IsValueType()) - { - // value types always have default constructor - // check whether there is a constructor that matches with non-writable properties on value type - var constructor = GetImmutableConstructor(contract.NonNullableUnderlyingType, contract.Properties); - if (constructor != null) - { - contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); - contract.CreatorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties)); - } - } - } - - var extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType); - if (extensionDataMember != null) SetExtensionDataDelegates(contract, extensionDataMember); - - // serializing DirectoryInfo without ISerializable will stackoverflow - // https://github.com/JamesNK/Newtonsoft.Json/issues/1541 - if (Array.IndexOf(BlacklistedTypeNames, objectType.FullName) != -1) contract.OnSerializingCallbacks.Add(ThrowUnableToSerializeError); - - return contract; - } - - private static void ThrowUnableToSerializeError(object o, StreamingContext context) => - throw new JsonSerializationException("Unable to serialize instance of '{0}'.".FormatWith(CultureInfo.InvariantCulture, o.GetType())); - - private MemberInfo GetExtensionDataMemberForType(Type type) - { - var members = GetClassHierarchyForType(type) - .SelectMany(baseType => - { - IList m = new List(); - m.AddRange(baseType.GetProperties( - BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); - m.AddRange(baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); - - return m; - }); - - var extensionDataMember = members.LastOrDefault(m => - { - var memberType = m.MemberType(); - if (memberType != MemberTypes.Property && memberType != MemberTypes.Field) return false; - - // last instance of attribute wins on type if there are multiple - if (!m.IsDefined(typeof(JsonExtensionDataAttribute), false)) return false; - - if (!ReflectionUtils.CanReadMemberValue(m, true)) - throw new JsonException( - "Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, - GetClrTypeFullName(m.DeclaringType), m.Name)); - - var t = ReflectionUtils.GetMemberUnderlyingType(m); - - if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out var dictionaryType)) - { - var keyType = dictionaryType.GetGenericArguments()[0]; - var valueType = dictionaryType.GetGenericArguments()[1]; - - if (keyType.IsAssignableFrom(typeof(string)) && valueType.IsAssignableFrom(typeof(JToken))) return true; - } - - throw new JsonException( - "Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary.".FormatWith( - CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); - }); - - return extensionDataMember; - } - - private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member) - { - var extensionDataAttribute = ReflectionUtils.GetAttribute(member); - if (extensionDataAttribute == null) return; - - var t = ReflectionUtils.GetMemberUnderlyingType(member); - - ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out var dictionaryType); - - var keyType = dictionaryType!.GetGenericArguments()[0]; - var valueType = dictionaryType!.GetGenericArguments()[1]; - - Type createdType; - - // change type to a class if it is the base interface so it can be instantiated if needed - if (ReflectionUtils.IsGenericDefinition(t, typeof(IDictionary<,>))) - createdType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); - else - createdType = t; - - var getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(member); - - if (extensionDataAttribute.ReadData) - { - var setExtensionDataDictionary = ReflectionUtils.CanSetMemberValue(member, true, false) - ? JsonTypeReflector.ReflectionDelegateFactory.CreateSet(member) - : null; - var createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(createdType); - var setMethod = t.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null) - ?.GetSetMethod(); - if (setMethod == null) - { - // Item is explicitly implemented and non-public - // get from dictionary interface - setMethod = dictionaryType! - .GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null) - ?.GetSetMethod(); - } - - var setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMethod!); - - ExtensionDataSetter extensionDataSetter = (o, key, value) => - { - var dictionary = getExtensionDataDictionary(o); - if (dictionary == null) - { - if (setExtensionDataDictionary == null) - throw new JsonSerializationException( - "Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set." - .FormatWith(CultureInfo.InvariantCulture, member.Name)); - - dictionary = createExtensionDataDictionary(); - setExtensionDataDictionary(o, dictionary); - } - - setExtensionDataDictionaryValue(dictionary, key, value); - }; - - contract.ExtensionDataSetter = extensionDataSetter; - } - - if (extensionDataAttribute.WriteData) - { - var enumerableWrapper = typeof(EnumerableDictionaryWrapper<,>).MakeGenericType(keyType, valueType); - var constructors = enumerableWrapper.GetConstructors().First(); - var createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructors); - - ExtensionDataGetter extensionDataGetter = o => - { - var dictionary = getExtensionDataDictionary(o); - if (dictionary == null) return null; - - return (IEnumerable>)createEnumerableWrapper(dictionary); - }; - - contract.ExtensionDataGetter = extensionDataGetter; - } - - contract.ExtensionDataValueType = valueType; - } - - // leave as class instead of struct - // will be always return as an interface and boxed - internal class EnumerableDictionaryWrapper : IEnumerable> - { - private readonly IEnumerable> _e; - - internal EnumerableDictionaryWrapper(IEnumerable> e) - { - ValidationUtils.ArgumentNotNull(e, nameof(e)); - _e = e; - } - - public IEnumerator> GetEnumerator() - { - foreach (var item in _e) yield return new KeyValuePair(item.Key!, item.Value!); - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - private ConstructorInfo? GetAttributeConstructor(Type objectType) - { - var en = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)) - .GetEnumerator(); - - if (en.MoveNext()) - { - var conInfo = en.Current; - if (en.MoveNext()) throw new JsonException("Multiple constructors with the JsonConstructorAttribute."); - - return conInfo; - } - - // little hack to get Version objects to deserialize correctly - if (objectType == typeof(Version)) return objectType.GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int) }); - - return null; - } - - private ConstructorInfo? GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties) - { - IEnumerable constructors = objectType.GetConstructors(); - var en = constructors.GetEnumerator(); - if (en.MoveNext()) - { - var constructor = en.Current; - if (!en.MoveNext()) - { - var parameters = constructor.GetParameters(); - if (parameters.Length > 0) - { - foreach (var parameterInfo in parameters) - { - var memberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); - if (memberProperty == null || memberProperty.Writable) return null; - } - - return constructor; - } - } - } - - return null; - } - - private ConstructorInfo? GetParameterizedConstructor(Type objectType) - { -#if PORTABLE - IEnumerable constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); - IEnumerator en = constructors.GetEnumerator(); - if (en.MoveNext()) - { - ConstructorInfo conInfo = en.Current; - if (!en.MoveNext()) - { - return conInfo; - } - } -#else - var constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); - if (constructors.Length == 1) return constructors[0]; -#endif - return null; - } - - /// - /// Creates the constructor parameters. - /// - /// The constructor to create properties for. - /// The type's member properties. - /// Properties for the given . - protected virtual IList CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties) - { - var constructorParameters = constructor.GetParameters(); - - var parameterCollection = new JsonPropertyCollection(constructor.DeclaringType); - - foreach (var parameterInfo in constructorParameters) - { - if (parameterInfo.Name == null) continue; - - var matchingMemberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); - - // ensure that property will have a name from matching property or from parameterinfo - // parameterinfo could have no name if generated by a proxy (I'm looking at you Castle) - if (matchingMemberProperty != null || parameterInfo.Name != null) - { - var property = CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo); - - if (property != null) parameterCollection.AddProperty(property); - } - } - - return parameterCollection; - } - - private JsonProperty? MatchProperty(JsonPropertyCollection properties, string name, Type type) - { - // it is possible to generate a member with a null name using Reflection.Emit - // protect against an ArgumentNullException from GetClosestMatchProperty by testing for null here - if (name == null) return null; - - var property = properties.GetClosestMatchProperty(name); - // must match type as well as name - if (property == null || property.PropertyType != type) return null; - - return property; - } - - /// - /// Creates a for the given . - /// - /// The matching member property. - /// The constructor parameter. - /// A created for the given . - protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty? matchingMemberProperty, ParameterInfo parameterInfo) - { - var property = new JsonProperty(); - property.PropertyType = parameterInfo.ParameterType; - property.AttributeProvider = new ReflectionAttributeProvider(parameterInfo); - - SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, - MemberSerialization.OptOut, out _); - - property.Readable = false; - property.Writable = true; - - // "inherit" values from matching member property if unset on parameter - if (matchingMemberProperty != null) - { - property.PropertyName = property.PropertyName != parameterInfo.Name ? property.PropertyName : matchingMemberProperty.PropertyName; - property.Converter = property.Converter ?? matchingMemberProperty.Converter; - - if (!property._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue) - property.DefaultValue = matchingMemberProperty.DefaultValue; - - property._required = property._required ?? matchingMemberProperty._required; - property.IsReference = property.IsReference ?? matchingMemberProperty.IsReference; - property.NullValueHandling = property.NullValueHandling ?? matchingMemberProperty.NullValueHandling; - property.DefaultValueHandling = property.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling; - property.ReferenceLoopHandling = property.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling; - property.ObjectCreationHandling = property.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling; - property.TypeNameHandling = property.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling; - } - - return property; - } - - /// - /// Resolves the default for the contract. - /// - /// Type of the object. - /// The contract's default . - protected virtual JsonConverter? ResolveContractConverter(Type objectType) => JsonTypeReflector.GetJsonConverter(objectType); - - private Func GetDefaultCreator(Type createdType) => - JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(createdType); - -#if NET35 - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = - "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")] -#endif - private void InitializeContract(JsonContract contract) - { - var containerAttribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); - if (containerAttribute != null) contract.IsReference = containerAttribute._isReference; -#if HAVE_DATA_CONTRACTS - else - { - DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); - // doesn't have a null value - if (dataContractAttribute != null && dataContractAttribute.IsReference) - { - contract.IsReference = true; - } - } -#endif - - contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType); - - // then see whether object is compatible with any of the built in converters - contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType); - - if (contract.IsInstantiable - && (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true) || contract.CreatedType.IsValueType())) - { - contract.DefaultCreator = GetDefaultCreator(contract.CreatedType); - - contract.DefaultCreatorNonPublic = !contract.CreatedType.IsValueType() && - ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null; - } - - ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType); - } - - private void ResolveCallbackMethods(JsonContract contract, Type t) - { - GetCallbackMethodsForType( - t, - out var onSerializing, - out var onSerialized, - out var onDeserializing, - out var onDeserialized, - out var onError); - - if (onSerializing != null) contract.OnSerializingCallbacks.AddRange(onSerializing); - - if (onSerialized != null) contract.OnSerializedCallbacks.AddRange(onSerialized); - - if (onDeserializing != null) contract.OnDeserializingCallbacks.AddRange(onDeserializing); - - if (onDeserialized != null) contract.OnDeserializedCallbacks.AddRange(onDeserialized); - - if (onError != null) contract.OnErrorCallbacks.AddRange(onError); - } - - private void GetCallbackMethodsForType(Type type, out List? onSerializing, - out List? onSerialized, out List? onDeserializing, - out List? onDeserialized, out List? onError - ) - { - onSerializing = null; - onSerialized = null; - onDeserializing = null; - onDeserialized = null; - onError = null; - - foreach (var baseType in GetClassHierarchyForType(type)) - { - // while we allow more than one OnSerialized total, only one can be defined per class - MethodInfo? currentOnSerializing = null; - MethodInfo? currentOnSerialized = null; - MethodInfo? currentOnDeserializing = null; - MethodInfo? currentOnDeserialized = null; - MethodInfo? currentOnError = null; - - var skipSerializing = ShouldSkipSerializing(baseType); - var skipDeserialized = ShouldSkipDeserialized(baseType); - - foreach (var method in baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance - | BindingFlags.DeclaredOnly)) - { - // compact framework errors when getting parameters for a generic method - // lame, but generic methods should not be callbacks anyway - if (method.ContainsGenericParameters) continue; - - Type? prevAttributeType = null; - var parameters = method.GetParameters(); - - if (!skipSerializing && IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentOnSerializing, - ref prevAttributeType)) - { - onSerializing = onSerializing ?? new List(); - onSerializing.Add(JsonContract.CreateSerializationCallback(method)); - currentOnSerializing = method; - } - if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentOnSerialized, ref prevAttributeType)) - { - onSerialized = onSerialized ?? new List(); - onSerialized.Add(JsonContract.CreateSerializationCallback(method)); - currentOnSerialized = method; - } - if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentOnDeserializing, ref prevAttributeType)) - { - onDeserializing = onDeserializing ?? new List(); - onDeserializing.Add(JsonContract.CreateSerializationCallback(method)); - currentOnDeserializing = method; - } - if (!skipDeserialized && IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentOnDeserialized, - ref prevAttributeType)) - { - onDeserialized = onDeserialized ?? new List(); - onDeserialized.Add(JsonContract.CreateSerializationCallback(method)); - currentOnDeserialized = method; - } - if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentOnError, ref prevAttributeType)) - { - onError = onError ?? new List(); - onError.Add(JsonContract.CreateSerializationErrorCallback(method)); - currentOnError = method; - } - } - } - } - - private static bool IsConcurrentOrObservableCollection(Type t) - { - if (t.IsGenericType()) - { - var definition = t.GetGenericTypeDefinition(); - - switch (definition.FullName) - { - case "System.Collections.Concurrent.ConcurrentQueue`1": - case "System.Collections.Concurrent.ConcurrentStack`1": - case "System.Collections.Concurrent.ConcurrentBag`1": - case JsonTypeReflector.ConcurrentDictionaryTypeName: - case "System.Collections.ObjectModel.ObservableCollection`1": - return true; - } - } - - return false; - } - - private static bool ShouldSkipDeserialized(Type t) - { - // ConcurrentDictionary throws an error in its OnDeserialized so ignore - http://json.codeplex.com/discussions/257093 - if (IsConcurrentOrObservableCollection(t)) return true; - -#if HAVE_FSHARP_TYPES - if (t.Name == FSharpUtils.FSharpSetTypeName || t.Name == FSharpUtils.FSharpMapTypeName) - { - return true; - } -#endif - - return false; - } - - private static bool ShouldSkipSerializing(Type t) - { - if (IsConcurrentOrObservableCollection(t)) return true; - -#if HAVE_FSHARP_TYPES - if (t.Name == FSharpUtils.FSharpSetTypeName || t.Name == FSharpUtils.FSharpMapTypeName) - { - return true; - } -#endif - - return false; - } - - private List GetClassHierarchyForType(Type type) - { - var ret = new List(); - - var current = type; - while (current != null && current != typeof(object)) - { - ret.Add(current); - current = current.BaseType(); - } - - // Return the class list in order of simple => complex - ret.Reverse(); - return ret; - } - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType) - { - var contract = new JsonDictionaryContract(objectType); - InitializeContract(contract); - - var containerAttribute = JsonTypeReflector.GetAttribute(objectType); - if (containerAttribute?.NamingStrategyType != null) - { - var namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute)!; - contract.DictionaryKeyResolver = s => namingStrategy.GetDictionaryKey(s); - } - else - contract.DictionaryKeyResolver = ResolveDictionaryKey; - - var overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); - - if (overrideConstructor != null) - { - var parameters = overrideConstructor.GetParameters(); - var expectedParameterType = contract.DictionaryKeyType != null && contract.DictionaryValueType != null - ? typeof(IEnumerable<>).MakeGenericType(typeof(KeyValuePair<,>).MakeGenericType(contract.DictionaryKeyType, - contract.DictionaryValueType)) - : typeof(IDictionary); - - if (parameters.Length == 0) - contract.HasParameterizedCreator = false; - else if (parameters.Length == 1 && expectedParameterType.IsAssignableFrom(parameters[0].ParameterType)) - contract.HasParameterizedCreator = true; - else - throw new JsonException( - "Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType, expectedParameterType)); - - contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor); - } - - return contract; - } - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonArrayContract CreateArrayContract(Type objectType) - { - var contract = new JsonArrayContract(objectType); - InitializeContract(contract); - - var overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); - - if (overrideConstructor != null) - { - var parameters = overrideConstructor.GetParameters(); - var expectedParameterType = contract.CollectionItemType != null - ? typeof(IEnumerable<>).MakeGenericType(contract.CollectionItemType) - : typeof(IEnumerable); - - if (parameters.Length == 0) - contract.HasParameterizedCreator = false; - else if (parameters.Length == 1 && expectedParameterType.IsAssignableFrom(parameters[0].ParameterType)) - contract.HasParameterizedCreator = true; - else - throw new JsonException( - "Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType, expectedParameterType)); - - contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(overrideConstructor); - } - - return contract; - } - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType) - { - var contract = new JsonPrimitiveContract(objectType); - InitializeContract(contract); - - return contract; - } - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonLinqContract CreateLinqContract(Type objectType) - { - var contract = new JsonLinqContract(objectType); - InitializeContract(contract); - - return contract; - } - -#if HAVE_BINARY_SERIALIZATION - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonISerializableContract CreateISerializableContract(Type objectType) - { - JsonISerializableContract contract = new JsonISerializableContract(objectType); - InitializeContract(contract); - - if (contract.IsInstantiable) - { - ConstructorInfo constructorInfo = - contract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] {typeof(SerializationInfo), typeof(StreamingContext)}, null); - if (constructorInfo != null) - { - ObjectConstructor creator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructorInfo); - - contract.ISerializableCreator = creator; - } - } - - return contract; - } -#endif - -#if HAVE_DYNAMIC - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonDynamicContract CreateDynamicContract(Type objectType) - { - JsonDynamicContract contract = new JsonDynamicContract(objectType); - InitializeContract(contract); - - JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetAttribute(objectType); - if (containerAttribute?.NamingStrategyType != null) - { - NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute)!; - contract.PropertyNameResolver = s => namingStrategy.GetDictionaryKey(s); - } - else - { - contract.PropertyNameResolver = ResolveDictionaryKey; - } - - contract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut)); - - return contract; - } -#endif - - /// - /// Creates a for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonStringContract CreateStringContract(Type objectType) - { - var contract = new JsonStringContract(objectType); - InitializeContract(contract); - - return contract; - } - - /// - /// Determines which contract type is created for the given type. - /// - /// Type of the object. - /// A for the given type. - protected virtual JsonContract CreateContract(Type objectType) - { - var t = ReflectionUtils.EnsureNotByRefType(objectType); - - if (IsJsonPrimitiveType(t)) return CreatePrimitiveContract(objectType); - - t = ReflectionUtils.EnsureNotNullableType(t); - var containerAttribute = JsonTypeReflector.GetCachedAttribute(t); - - if (containerAttribute is JsonObjectAttribute) return CreateObjectContract(objectType); - - if (containerAttribute is JsonArrayAttribute) return CreateArrayContract(objectType); - - if (containerAttribute is JsonDictionaryAttribute) return CreateDictionaryContract(objectType); - - if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken))) return CreateLinqContract(objectType); - - if (CollectionUtils.IsDictionaryType(t)) return CreateDictionaryContract(objectType); - - if (typeof(IEnumerable).IsAssignableFrom(t)) return CreateArrayContract(objectType); - - if (CanConvertToString(t)) return CreateStringContract(objectType); - -#if HAVE_BINARY_SERIALIZATION - if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t) && JsonTypeReflector.IsSerializable(t)) - { - return CreateISerializableContract(objectType); - } -#endif - -#if HAVE_DYNAMIC - if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t)) - { - return CreateDynamicContract(objectType); - } -#endif - -#if HAVE_ICONVERTIBLE - // tested last because it is not possible to automatically deserialize custom IConvertible types - if (IsIConvertible(t)) - { - return CreatePrimitiveContract(t); - } -#endif - - return CreateObjectContract(objectType); - } - - internal static bool IsJsonPrimitiveType(Type t) - { - var typeCode = ConvertUtils.GetTypeCode(t); - - return typeCode != PrimitiveTypeCode.Empty && typeCode != PrimitiveTypeCode.Object; - } - -#if HAVE_ICONVERTIBLE - internal static bool IsIConvertible(Type t) - { - if (typeof(IConvertible).IsAssignableFrom(t) - || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t)))) - { - return !typeof(JToken).IsAssignableFrom(t); - } - - return false; - } -#endif - - internal static bool CanConvertToString(Type type) - { -#if HAVE_TYPE_DESCRIPTOR - if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out _)) - { - return true; - } -#endif - - if (type == typeof(Type) || type.IsSubclassOf(typeof(Type))) return true; - - return false; - } - - private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo? currentCallback, - ref Type? prevAttributeType - ) - { - if (!method.IsDefined(attributeType, false)) return false; - - if (currentCallback != null) - throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, - method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType)); - - if (prevAttributeType != null) - throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith( - CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method)); - - if (method.IsVirtual) - throw new JsonException( - "Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, - GetClrTypeFullName(method.DeclaringType), attributeType)); - - if (method.ReturnType != typeof(void)) - throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, - GetClrTypeFullName(method.DeclaringType), method)); - - if (attributeType == typeof(OnErrorAttribute)) - { - if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) - || parameters[1].ParameterType != typeof(ErrorContext)) - throw new JsonException( - "Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith( - CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), - typeof(ErrorContext))); - } - else - { - if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext)) - throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith( - CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext))); - } - - prevAttributeType = attributeType; - - return true; - } - - internal static string GetClrTypeFullName(Type type) - { - if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters()) return type.FullName; - - return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name); - } - - /// - /// Creates properties for the given . - /// - /// The type to create properties for. - /// /// - /// The member serialization mode for the type. - /// Properties for the given . - protected virtual IList CreateProperties(Type type, MemberSerialization memberSerialization) - { - var members = GetSerializableMembers(type); - if (members == null) throw new JsonSerializationException("Null collection of serializable members returned."); - - var nameTable = GetNameTable(); - - var properties = new JsonPropertyCollection(type); - - foreach (var member in members) - { - var property = CreateProperty(member, memberSerialization); - - if (property != null) - { - // nametable is not thread-safe for multiple writers - lock (nameTable) property.PropertyName = nameTable.Add(property.PropertyName!); - - properties.AddProperty(property); - } - } - - IList orderedProperties = properties.OrderBy(p => p.Order ?? -1).ToList(); - return orderedProperties; - } - - internal virtual DefaultJsonNameTable GetNameTable() => _nameTable; - - /// - /// Creates the used by the serializer to get and set values from a member. - /// - /// The member. - /// The used by the serializer to get and set values from a member. - protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) - { - // warning - this method use to cause errors with Intellitrace. Retest in VS Ultimate after changes - IValueProvider valueProvider; - -#if !(PORTABLE40 || PORTABLE || DOTNET || NET472 || NETSTANDARD2_0 || NET5_0_OR_GREATER) - if (DynamicCodeGeneration) - { - valueProvider = new DynamicValueProvider(member); - } - else - { - valueProvider = new ReflectionValueProvider(member); - } -#elif !(PORTABLE40) - valueProvider = new ExpressionValueProvider(member); -#else - valueProvider = new ReflectionValueProvider(member); -#endif - - return valueProvider; - } - - /// - /// Creates a for the given . - /// - /// The member's parent . - /// The member to create a for. - /// A created for the given . - protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var property = new JsonProperty(); - property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); - property.DeclaringType = member.DeclaringType; - property.ValueProvider = CreateMemberValueProvider(member); - property.AttributeProvider = new ReflectionAttributeProvider(member); - - SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out var allowNonPublicAccess); - - if (memberSerialization != MemberSerialization.Fields) - { - property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess); - property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, property.HasMemberAttribute); - } - else - { - // write to readonly fields - property.Readable = true; - property.Writable = true; - } - - if (!IgnoreShouldSerializeMembers) property.ShouldSerialize = CreateShouldSerializeTest(member); - - if (!IgnoreIsSpecifiedMembers) SetIsSpecifiedActions(property, member, allowNonPublicAccess); - - return property; - } - - private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, - MemberSerialization memberSerialization, out bool allowNonPublicAccess - ) - { -#if HAVE_DATA_CONTRACTS - DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); - - MemberInfo? memberInfo = attributeProvider as MemberInfo; - - DataMemberAttribute? dataMemberAttribute; - if (dataContractAttribute != null && memberInfo != null) - { - dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo)memberInfo); - } - else - { - dataMemberAttribute = null; - } -#endif - - var propertyAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - var requiredAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - - string mappedName; - bool hasSpecifiedName; - if (propertyAttribute?.PropertyName != null) - { - mappedName = propertyAttribute.PropertyName; - hasSpecifiedName = true; - } -#if HAVE_DATA_CONTRACTS - else if (dataMemberAttribute?.Name != null) - { - mappedName = dataMemberAttribute.Name; - hasSpecifiedName = true; - } -#endif - else - { - mappedName = name; - hasSpecifiedName = false; - } - - var containerAttribute = JsonTypeReflector.GetAttribute(declaringType); - - NamingStrategy? namingStrategy; - if (propertyAttribute?.NamingStrategyType != null) - namingStrategy = - JsonTypeReflector.CreateNamingStrategyInstance(propertyAttribute.NamingStrategyType, propertyAttribute.NamingStrategyParameters); - else if (containerAttribute?.NamingStrategyType != null) - namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute); - else - namingStrategy = NamingStrategy; - - if (namingStrategy != null) - property.PropertyName = namingStrategy.GetPropertyName(mappedName, hasSpecifiedName); - else - property.PropertyName = ResolvePropertyName(mappedName); - - property.UnderlyingName = name; - - var hasMemberAttribute = false; - if (propertyAttribute != null) - { - property._required = propertyAttribute._required; - property.Order = propertyAttribute._order; - property.DefaultValueHandling = propertyAttribute._defaultValueHandling; - hasMemberAttribute = true; - property.NullValueHandling = propertyAttribute._nullValueHandling; - property.ReferenceLoopHandling = propertyAttribute._referenceLoopHandling; - property.ObjectCreationHandling = propertyAttribute._objectCreationHandling; - property.TypeNameHandling = propertyAttribute._typeNameHandling; - property.IsReference = propertyAttribute._isReference; - - property.ItemIsReference = propertyAttribute._itemIsReference; - property.ItemConverter = propertyAttribute.ItemConverterType != null - ? JsonTypeReflector.CreateJsonConverterInstance(propertyAttribute.ItemConverterType, propertyAttribute.ItemConverterParameters) - : null; - property.ItemReferenceLoopHandling = propertyAttribute._itemReferenceLoopHandling; - property.ItemTypeNameHandling = propertyAttribute._itemTypeNameHandling; - } - else - { - property.NullValueHandling = null; - property.ReferenceLoopHandling = null; - property.ObjectCreationHandling = null; - property.TypeNameHandling = null; - property.IsReference = null; - property.ItemIsReference = null; - property.ItemConverter = null; - property.ItemReferenceLoopHandling = null; - property.ItemTypeNameHandling = null; -#if HAVE_DATA_CONTRACTS - if (dataMemberAttribute != null) - { - property._required = (dataMemberAttribute.IsRequired) ? Required.AllowNull : Required.Default; - property.Order = (dataMemberAttribute.Order != -1) ? (int?)dataMemberAttribute.Order : null; - property.DefaultValueHandling = - (!dataMemberAttribute.EmitDefaultValue) ? (DefaultValueHandling?)DefaultValueHandling.Ignore : null; - hasMemberAttribute = true; - } -#endif - } - - if (requiredAttribute != null) - { - property._required = Required.Always; - hasMemberAttribute = true; - } - - property.HasMemberAttribute = hasMemberAttribute; - - var hasJsonIgnoreAttribute = - JsonTypeReflector.GetAttribute(attributeProvider) != null - // automatically ignore extension data dictionary property if it is public - || JsonTypeReflector.GetAttribute(attributeProvider) != null -#if HAVE_NON_SERIALIZED_ATTRIBUTE - || JsonTypeReflector.IsNonSerializable(attributeProvider) -#endif - ; - - if (memberSerialization != MemberSerialization.OptIn) - { - var hasIgnoreDataMemberAttribute = false; - -#if HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE - hasIgnoreDataMemberAttribute = (JsonTypeReflector.GetAttribute(attributeProvider) != null); -#endif - - // ignored if it has JsonIgnore or NonSerialized or IgnoreDataMember attributes - property.Ignored = hasJsonIgnoreAttribute || hasIgnoreDataMemberAttribute; - } - else - { - // ignored if it has JsonIgnore/NonSerialized or does not have DataMember or JsonProperty attributes - property.Ignored = hasJsonIgnoreAttribute || !hasMemberAttribute; - } - - // resolve converter for property - // the class type might have a converter but the property converter takes precedence - property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider); - - var defaultValueAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - if (defaultValueAttribute != null) property.DefaultValue = defaultValueAttribute.Value; - - allowNonPublicAccess = false; -#pragma warning disable 618 - if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic) allowNonPublicAccess = true; -#pragma warning restore 618 - if (hasMemberAttribute) allowNonPublicAccess = true; - if (memberSerialization == MemberSerialization.Fields) allowNonPublicAccess = true; - } - - private Predicate? CreateShouldSerializeTest(MemberInfo member) - { - var shouldSerializeMethod = - member.DeclaringType.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes); - - if (shouldSerializeMethod == null || shouldSerializeMethod.ReturnType != typeof(bool)) return null; - - var shouldSerializeCall = - JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(shouldSerializeMethod); - - return o => (bool)shouldSerializeCall(o)!; - } - - private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) - { - MemberInfo? specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - if (specifiedMember == null) - specifiedMember = member.DeclaringType.GetField(member.Name + JsonTypeReflector.SpecifiedPostfix, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - if (specifiedMember == null || ReflectionUtils.GetMemberUnderlyingType(specifiedMember) != typeof(bool)) return; - - var specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(specifiedMember)!; - - property.GetIsSpecified = o => (bool)(specifiedPropertyGet(o) ?? false); - - if (ReflectionUtils.CanSetMemberValue(specifiedMember, allowNonPublicAccess, false)) - property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet(specifiedMember); - } - - /// - /// Resolves the name of the property. - /// - /// Name of the property. - /// Resolved name of the property. - protected virtual string ResolvePropertyName(string propertyName) - { - if (NamingStrategy != null) return NamingStrategy.GetPropertyName(propertyName, false); - - return propertyName; - } - - /// - /// Resolves the name of the extension data. By default no changes are made to extension data names. - /// - /// Name of the extension data. - /// Resolved name of the extension data. - protected virtual string ResolveExtensionDataName(string extensionDataName) - { - if (NamingStrategy != null) return NamingStrategy.GetExtensionDataName(extensionDataName); - - return extensionDataName; - } - - /// - /// Resolves the key of the dictionary. By default is used to resolve dictionary keys. - /// - /// Key of the dictionary. - /// Resolved key of the dictionary. - protected virtual string ResolveDictionaryKey(string dictionaryKey) - { - if (NamingStrategy != null) return NamingStrategy.GetDictionaryKey(dictionaryKey); - - return ResolvePropertyName(dictionaryKey); - } - - /// - /// Gets the resolved name of the property. - /// - /// Name of the property. - /// Name of the property. - public string GetResolvedPropertyName(string propertyName) => - // this is a new method rather than changing the visibility of ResolvePropertyName to avoid - // a breaking change for anyone who has overidden the method - ResolvePropertyName(propertyName); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultNamingStrategy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultNamingStrategy.cs deleted file mode 100644 index 89cd90ae2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultNamingStrategy.cs +++ /dev/null @@ -1,16 +0,0 @@ -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// The default naming strategy. Property names and dictionary keys are unchanged. - /// - internal class DefaultNamingStrategy : NamingStrategy - { - /// - /// Resolves the specified property name. - /// - /// The property name to resolve. - /// The resolved property name. - protected override string ResolvePropertyName(string name) => name; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs deleted file mode 100644 index a38d822cf..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs +++ /dev/null @@ -1,75 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class DefaultReferenceResolver : IReferenceResolver - { - private int _referenceCount; - - private BidirectionalDictionary GetMappings(object context) - { - if (!(context is JsonSerializerInternalBase internalSerializer)) - { - if (context is JsonSerializerProxy proxy) - internalSerializer = proxy.GetInternalSerializer(); - else - throw new JsonException("The DefaultReferenceResolver can only be used internally."); - } - - return internalSerializer.DefaultReferenceMappings; - } - - public object ResolveReference(object context, string reference) - { - GetMappings(context).TryGetByFirst(reference, out var value); - return value; - } - - public string GetReference(object context, object value) - { - var mappings = GetMappings(context); - - if (!mappings.TryGetBySecond(value, out var reference)) - { - _referenceCount++; - reference = _referenceCount.ToString(CultureInfo.InvariantCulture); - mappings.Set(reference, value); - } - - return reference; - } - - public void AddReference(object context, string reference, object value) => GetMappings(context).Set(reference, value); - - public bool IsReferenced(object context, object value) => GetMappings(context).TryGetBySecond(value, out _); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs deleted file mode 100644 index e6485450c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs +++ /dev/null @@ -1,200 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// The default serialization binder used when resolving and loading classes from type names. - /// - internal class DefaultSerializationBinder - : -#pragma warning disable 618 - SerializationBinder, -#pragma warning restore 618 - ISerializationBinder - { - internal static readonly DefaultSerializationBinder Instance = new(); - - private readonly ThreadSafeStore, Type> _typeCache; - - /// - /// Initializes a new instance of the class. - /// - public DefaultSerializationBinder() => _typeCache = new ThreadSafeStore, Type>(GetTypeFromTypeNameKey); - - private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) - { - var assemblyName = typeNameKey.Value1; - var typeName = typeNameKey.Value2; - - if (assemblyName != null) - { - Assembly assembly; - -#if !(DOTNET || PORTABLE40 || PORTABLE) - // look, I don't like using obsolete methods as much as you do but this is the only way - // Assembly.Load won't check the GAC for a partial name -#pragma warning disable 618,612 - assembly = Assembly.LoadWithPartialName(assemblyName); -#pragma warning restore 618,612 -#elif DOTNET || PORTABLE - assembly = Assembly.Load(new AssemblyName(assemblyName)); -#else - assembly = Assembly.Load(assemblyName); -#endif - -#if HAVE_APP_DOMAIN - if (assembly == null) - { - // will find assemblies loaded with Assembly.LoadFile outside of the main directory - Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly a in loadedAssemblies) - { - // check for both full name or partial name match - if (a.FullName == assemblyName || a.GetName().Name == assemblyName) - { - assembly = a; - break; - } - } - } -#endif - - if (assembly == null) - throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, assemblyName)); - - var type = assembly.GetType(typeName); - if (type == null) - { - // if generic type, try manually parsing the type arguments for the case of dynamically loaded assemblies - // example generic typeName format: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] - if (typeName.IndexOf('`') >= 0) - { - try - { - type = GetGenericTypeFromTypeName(typeName, assembly); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeName, assembly.FullName), - ex); - } - } - - if (type == null) - throw new JsonSerializationException( - "Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeName, assembly.FullName)); - } - - return type; - } - return Type.GetType(typeName); - } - - private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly) - { - Type? type = null; - var openBracketIndex = typeName.IndexOf('['); - if (openBracketIndex >= 0) - { - var genericTypeDefName = typeName.Substring(0, openBracketIndex); - var genericTypeDef = assembly.GetType(genericTypeDefName); - if (genericTypeDef != null) - { - var genericTypeArguments = new List(); - var scope = 0; - var typeArgStartIndex = 0; - var endIndex = typeName.Length - 1; - for (var i = openBracketIndex + 1; i < endIndex; ++i) - { - var current = typeName[i]; - switch (current) - { - case '[': - if (scope == 0) typeArgStartIndex = i + 1; - ++scope; - break; - case ']': - --scope; - if (scope == 0) - { - var typeArgAssemblyQualifiedName = typeName.Substring(typeArgStartIndex, i - typeArgStartIndex); - - var typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(typeArgAssemblyQualifiedName); - genericTypeArguments.Add(GetTypeByName(typeNameKey)); - } - break; - } - } - - type = genericTypeDef.MakeGenericType(genericTypeArguments.ToArray()); - } - } - - return type; - } - - private Type GetTypeByName(StructMultiKey typeNameKey) => _typeCache.Get(typeNameKey); - - /// - /// When overridden in a derived class, controls the binding of a serialized object to a type. - /// - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object. - /// - /// The type of the object the formatter creates a new instance of. - /// - public override Type BindToType(string? assemblyName, string typeName) => - GetTypeByName(new StructMultiKey(assemblyName, typeName)); - - /// - /// When overridden in a derived class, controls the binding of a serialized object to a type. - /// - /// The type of the object the formatter creates a new instance of. - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object. - public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName) - { -#if !HAVE_FULL_REFLECTION - assemblyName = serializedType.GetTypeInfo().Assembly.FullName; - typeName = serializedType.FullName; -#else - assemblyName = serializedType.Assembly.FullName; - typeName = serializedType.FullName; -#endif - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs deleted file mode 100644 index e19c1dd9c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs +++ /dev/null @@ -1,80 +0,0 @@ -#if HAVE_TRACE_WRITER -using System; -using System.Diagnostics; -using DiagnosticsTrace = System.Diagnostics.Trace; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Represents a trace writer that writes to the application's instances. - /// - internal class DiagnosticsTraceWriter : ITraceWriter - { - /// - /// Gets the that will be used to filter the trace messages passed to the writer. - /// For example a filter level of will exclude messages and include , - /// and messages. - /// - /// - /// The that will be used to filter the trace messages passed to the writer. - /// - public TraceLevel LevelFilter { get; set; } - - private TraceEventType GetTraceEventType(TraceLevel level) - { - switch (level) - { - case TraceLevel.Error: - return TraceEventType.Error; - case TraceLevel.Warning: - return TraceEventType.Warning; - case TraceLevel.Info: - return TraceEventType.Information; - case TraceLevel.Verbose: - return TraceEventType.Verbose; - default: - throw new ArgumentOutOfRangeException(nameof(level)); - } - } - - /// - /// Writes the specified trace level, message and optional exception. - /// - /// The at which to write this trace. - /// The trace message. - /// The trace exception. This parameter is optional. - public void Trace(TraceLevel level, string message, Exception? ex) - { - if (level == TraceLevel.Off) - { - return; - } - - TraceEventCache eventCache = new TraceEventCache(); - TraceEventType traceEventType = GetTraceEventType(level); - - foreach (TraceListener listener in DiagnosticsTrace.Listeners) - { - if (!listener.IsThreadSafe) - { - lock (listener) - { - listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); - } - } - else - { - listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); - } - - if (DiagnosticsTrace.AutoFlush) - { - listener.Flush(); - } - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DynamicValueProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DynamicValueProvider.cs deleted file mode 100644 index da193fb3a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/DynamicValueProvider.cs +++ /dev/null @@ -1,129 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if NET462 -using System; -using System.Collections.Generic; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif -using System.Text; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using System.Globalization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Get and set values for a using dynamic methods. - /// - internal class DynamicValueProvider : IValueProvider - { - private readonly MemberInfo _memberInfo; - private Func? _getter; - private Action? _setter; - - /// - /// Initializes a new instance of the class. - /// - /// The member info. - public DynamicValueProvider(MemberInfo memberInfo) - { - ValidationUtils.ArgumentNotNull(memberInfo, nameof(memberInfo)); - _memberInfo = memberInfo; - } - - /// - /// Sets the value. - /// - /// The target to set the value on. - /// The value to set on the target. - public void SetValue(object target, object? value) - { - try - { - if (_setter == null) - { - _setter = DynamicReflectionDelegateFactory.Instance.CreateSet(_memberInfo); - } - -#if DEBUG - // dynamic method doesn't check whether the type is 'legal' to set - // add this check for unit tests - if (value == null) - { - if (!ReflectionUtils.IsNullable(ReflectionUtils.GetMemberUnderlyingType(_memberInfo))) - { - throw new JsonSerializationException( - "Incompatible value. Cannot set {0} to null.".FormatWith(CultureInfo.InvariantCulture, _memberInfo)); - } - } - else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsAssignableFrom(value.GetType())) - { - throw new JsonSerializationException( - "Incompatible value. Cannot set {0} to type {1}.".FormatWith(CultureInfo.InvariantCulture, _memberInfo, value.GetType())); - } -#endif - - _setter(target, value); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - - /// - /// Gets the value. - /// - /// The target to get the value from. - /// The value. - public object? GetValue(object target) - { - try - { - if (_getter == null) - { - _getter = DynamicReflectionDelegateFactory.Instance.CreateGet(_memberInfo); - } - - return _getter(target); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorContext.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorContext.cs deleted file mode 100644 index 1ac637627..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorContext.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Provides information surrounding an error. - /// - internal class ErrorContext - { - internal ErrorContext(object? originalObject, object? member, string path, Exception error) - { - OriginalObject = originalObject; - Member = member; - Error = error; - Path = path; - } - - /// - /// Gets the error. - /// - /// The error. - public Exception Error { get; } - - /// - /// Gets or sets a value indicating whether this is handled. - /// - /// true if handled; otherwise, false. - public bool Handled { get; set; } - - /// - /// Gets the member that caused the error. - /// - /// The member that caused the error. - public object? Member { get; } - - /// - /// Gets the original object that caused the error. - /// - /// The original object that caused the error. - public object? OriginalObject { get; } - - /// - /// Gets the path of the JSON location where the error occurred. - /// - /// The path of the JSON location where the error occurred. - public string Path { get; } - - internal bool Traced { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorEventArgs.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorEventArgs.cs deleted file mode 100644 index 8afe78bd8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ErrorEventArgs.cs +++ /dev/null @@ -1,61 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Provides data for the Error event. - /// - internal class ErrorEventArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// The current object. - /// The error context. - public ErrorEventArgs(object? currentObject, ErrorContext errorContext) - { - CurrentObject = currentObject; - ErrorContext = errorContext; - } - - /// - /// Gets the current object the error event is being raised against. - /// - /// The current object the error event is being raised against. - public object? CurrentObject { get; } - - /// - /// Gets the error context. - /// - /// The error context. - public ErrorContext ErrorContext { get; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs deleted file mode 100644 index faf89ca59..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs +++ /dev/null @@ -1,116 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if !(NET20 || NET35) - -using System; -using System.Globalization; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Get and set values for a using dynamic methods. - /// - internal class ExpressionValueProvider : IValueProvider - { - private readonly MemberInfo _memberInfo; - - /// - /// Initializes a new instance of the class. - /// - /// The member info. - public ExpressionValueProvider(MemberInfo memberInfo) - { - ValidationUtils.ArgumentNotNull(memberInfo, nameof(memberInfo)); - _memberInfo = memberInfo; - } - - private Func? _getter; - private Action? _setter; - - /// - /// Sets the value. - /// - /// The target to set the value on. - /// The value to set on the target. - public void SetValue(object target, object? value) - { - try - { - if (_setter == null) _setter = ExpressionReflectionDelegateFactory.Instance.CreateSet(_memberInfo); - -#if DEBUG - // dynamic method doesn't check whether the type is 'legal' to set - // add this check for unit tests - if (value == null) - { - if (!ReflectionUtils.IsNullable(ReflectionUtils.GetMemberUnderlyingType(_memberInfo))) - throw new JsonSerializationException( - "Incompatible value. Cannot set {0} to null.".FormatWith(CultureInfo.InvariantCulture, _memberInfo)); - } - else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsAssignableFrom(value.GetType())) - throw new JsonSerializationException( - "Incompatible value. Cannot set {0} to type {1}.".FormatWith(CultureInfo.InvariantCulture, _memberInfo, value.GetType())); -#endif - - _setter(target, value); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - - /// - /// Gets the value. - /// - /// The target to get the value from. - /// The value. - public object? GetValue(object target) - { - try - { - if (_getter == null) _getter = ExpressionReflectionDelegateFactory.Instance.CreateGet(_memberInfo); - - return _getter(target); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/FormatterConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/FormatterConverter.cs deleted file mode 100644 index 045d6b626..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/FormatterConverter.cs +++ /dev/null @@ -1,110 +0,0 @@ -#if HAVE_BINARY_SERIALIZATION && !HAVE_BINARY_FORMATTER -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class FormatterConverter : IFormatterConverter - { - public object Convert(object value, Type type) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ChangeType(value, type, CultureInfo.InvariantCulture); - } - - public object Convert(object value, TypeCode typeCode) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ChangeType(value, typeCode, CultureInfo.InvariantCulture); - } - - public bool ToBoolean(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToBoolean(value, CultureInfo.InvariantCulture); - } - - public byte ToByte(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToByte(value, CultureInfo.InvariantCulture); - } - - public char ToChar(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToChar(value, CultureInfo.InvariantCulture); - } - - public DateTime ToDateTime(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToDateTime(value, CultureInfo.InvariantCulture); - } - - public decimal ToDecimal(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToDecimal(value, CultureInfo.InvariantCulture); - } - - public double ToDouble(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToDouble(value, CultureInfo.InvariantCulture); - } - - public short ToInt16(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToInt16(value, CultureInfo.InvariantCulture); - } - - public int ToInt32(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToInt32(value, CultureInfo.InvariantCulture); - } - - public long ToInt64(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToInt64(value, CultureInfo.InvariantCulture); - } - - public sbyte ToSByte(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToSByte(value, CultureInfo.InvariantCulture); - } - - public float ToSingle(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToSingle(value, CultureInfo.InvariantCulture); - } - - public string ToString(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToString(value, CultureInfo.InvariantCulture); - } - - public ushort ToUInt16(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToUInt16(value, CultureInfo.InvariantCulture); - } - - public uint ToUInt32(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToUInt32(value, CultureInfo.InvariantCulture); - } - - public ulong ToUInt64(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - return System.Convert.ToUInt64(value, CultureInfo.InvariantCulture); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IAttributeProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IAttributeProvider.cs deleted file mode 100644 index a5dd985b3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IAttributeProvider.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Provides methods to get attributes. - /// - internal interface IAttributeProvider - { - /// - /// Returns a collection of all of the attributes, or an empty collection if there are no attributes. - /// - /// When true, look up the hierarchy chain for the inherited custom attribute. - /// A collection of s, or an empty collection. - IList GetAttributes(bool inherit); - - /// - /// Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. - /// - /// The type of the attributes. - /// When true, look up the hierarchy chain for the inherited custom attribute. - /// A collection of s, or an empty collection. - IList GetAttributes(Type attributeType, bool inherit); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IContractResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IContractResolver.cs deleted file mode 100644 index 6e84353fa..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IContractResolver.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Used by to resolve a for a given . - /// - /// - /// - /// - /// - internal interface IContractResolver - { - /// - /// Resolves the contract for a given type. - /// - /// The type to resolve a contract for. - /// The contract for a given type. - JsonContract ResolveContract(Type type); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IReferenceResolver.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IReferenceResolver.cs deleted file mode 100644 index 82873966d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IReferenceResolver.cs +++ /dev/null @@ -1,70 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Used to resolve references when serializing and deserializing JSON by the . - /// - internal interface IReferenceResolver - { - /// - /// Adds a reference to the specified object. - /// - /// The serialization context. - /// The reference. - /// The object to reference. - void AddReference(object context, string reference, object value); - - /// - /// Gets the reference for the specified object. - /// - /// The serialization context. - /// The object to get a reference for. - /// The reference to the object. - string GetReference(object context, object value); - - /// - /// Determines whether the specified object is referenced. - /// - /// The serialization context. - /// The object to test for a reference. - /// - /// true if the specified object is referenced; otherwise, false. - /// - bool IsReferenced(object context, object value); - - /// - /// Resolves a reference to its object. - /// - /// The serialization context. - /// The reference to resolve. - /// The object that was resolved from the reference. - object ResolveReference(object context, string reference); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ISerializationBinder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ISerializationBinder.cs deleted file mode 100644 index dfb09bd92..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ISerializationBinder.cs +++ /dev/null @@ -1,55 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Reflection; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Allows users to control class loading and mandate what class to load. - /// - internal interface ISerializationBinder - { - /// - /// When implemented, controls the binding of a serialized object to a type. - /// - /// The type of the object the formatter creates a new instance of. - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object. - void BindToName(Type serializedType, out string? assemblyName, out string? typeName); - - /// - /// When implemented, controls the binding of a serialized object to a type. - /// - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object - /// The type of the object the formatter creates a new instance of. - Type BindToType(string? assemblyName, string typeName); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ITraceWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ITraceWriter.cs deleted file mode 100644 index d717f07dd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ITraceWriter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Diagnostics; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Represents a trace writer. - /// - internal interface ITraceWriter - { - /// - /// Gets the that will be used to filter the trace messages passed to the writer. - /// For example a filter level of will exclude messages - /// and include , - /// and messages. - /// - /// The that will be used to filter the trace messages passed to the writer. - TraceLevel LevelFilter { get; } - - /// - /// Writes the specified trace level, message and optional exception. - /// - /// The at which to write this trace. - /// The trace message. - /// The trace exception. This parameter is optional. - void Trace(TraceLevel level, string message, Exception? ex); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IValueProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IValueProvider.cs deleted file mode 100644 index 06e4d790f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/IValueProvider.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Provides methods to get and set values. - /// - internal interface IValueProvider - { - /// - /// Gets the value. - /// - /// The target to get the value from. - /// The value. - object? GetValue(object target); - - /// - /// Sets the value. - /// - /// The target to set the value on. - /// The value to set on the target. - void SetValue(object target, object? value); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonArrayContract.cs deleted file mode 100644 index e0bf63ba8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonArrayContract.cs +++ /dev/null @@ -1,311 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ - -#else - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonArrayContract : JsonContainerContract - { - /// - /// Gets the of the collection items. - /// - /// The of the collection items. - public Type? CollectionItemType { get; } - - /// - /// Gets a value indicating whether the collection type is a multidimensional array. - /// - /// true if the collection type is a multidimensional array; otherwise, false. - public bool IsMultidimensionalArray { get; } - - private readonly Type? _genericCollectionDefinitionType; - - private Type? _genericWrapperType; - private ObjectConstructor? _genericWrapperCreator; - private Func? _genericTemporaryCollectionCreator; - - internal bool IsArray { get; } - internal bool ShouldCreateWrapper { get; } - internal bool CanDeserialize { get; private set; } - - private readonly ConstructorInfo? _parameterizedConstructor; - - private ObjectConstructor? _parameterizedCreator; - private ObjectConstructor? _overrideCreator; - - internal ObjectConstructor? ParameterizedCreator - { - get - { - if (_parameterizedCreator == null && _parameterizedConstructor != null) - _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); - - return _parameterizedCreator; - } - } - - /// - /// Gets or sets the function used to create the object. When set this function will override - /// . - /// - /// The function used to create the object. - public ObjectConstructor? OverrideCreator - { - get => _overrideCreator; - set - { - _overrideCreator = value; - // hacky - CanDeserialize = true; - } - } - - /// - /// Gets a value indicating whether the creator has a parameter with the collection values. - /// - /// true if the creator has a parameter with the collection values; otherwise, false. - public bool HasParameterizedCreator { get; set; } - - internal bool HasParameterizedCreatorInternal => - HasParameterizedCreator || _parameterizedCreator != null || _parameterizedConstructor != null; - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonArrayContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Array; - - // netcoreapp3.0 uses EmptyPartition for empty enumerable. Treat as an empty array. - IsArray = CreatedType.IsArray || - NonNullableUnderlyingType.IsGenericType() - && NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Linq.EmptyPartition`1"; - - bool canDeserialize; - - Type? tempCollectionType; - if (IsArray) - { - CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType); - IsReadOnlyOrFixedSize = true; - _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); - - canDeserialize = true; - IsMultidimensionalArray = CreatedType.IsArray && UnderlyingType.GetArrayRank() > 1; - } - else if (typeof(IList).IsAssignableFrom(NonNullableUnderlyingType)) - { - if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), - out _genericCollectionDefinitionType)) - CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; - else - CollectionItemType = ReflectionUtils.GetCollectionItemType(NonNullableUnderlyingType); - - if (NonNullableUnderlyingType == typeof(IList)) CreatedType = typeof(List); - - if (CollectionItemType != null) - _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); - - IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyCollection<>)); - canDeserialize = true; - } - else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), - out _genericCollectionDefinitionType)) - { - CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; - - if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>)) - || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IList<>))) - CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); - -#if HAVE_ISET - if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ISet<>))) - { - CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType); - } -#endif - - _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); - canDeserialize = true; - ShouldCreateWrapper = true; - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>), out tempCollectionType)) - { - CollectionItemType = tempCollectionType.GetGenericArguments()[0]; - - if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>)) - || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyList<>))) - { - CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType); - } - - _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); - _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(CreatedType, CollectionItemType); - -#if HAVE_FSHARP_TYPES - StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); -#endif - - IsReadOnlyOrFixedSize = true; - canDeserialize = HasParameterizedCreatorInternal; - } -#endif - else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IEnumerable<>), out tempCollectionType)) - { - CollectionItemType = tempCollectionType.GetGenericArguments()[0]; - - if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>))) - CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); - - _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); - -#if HAVE_FSHARP_TYPES - StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); -#endif - - if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - _genericCollectionDefinitionType = tempCollectionType; - - IsReadOnlyOrFixedSize = false; - ShouldCreateWrapper = false; - canDeserialize = true; - } - else - { - _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); - - IsReadOnlyOrFixedSize = true; - ShouldCreateWrapper = true; - canDeserialize = HasParameterizedCreatorInternal; - } - } - else - { - // types that implement IEnumerable and nothing else - canDeserialize = false; - ShouldCreateWrapper = true; - } - - CanDeserialize = canDeserialize; - -#if (NET20 || NET35) - if (CollectionItemType != null && ReflectionUtils.IsNullableType(CollectionItemType)) - { - // bug in .NET 2.0 & 3.5 that List> throws an error when adding null via IList.Add(object) - // wrapper will handle calling Add(T) instead - if (ReflectionUtils.InheritsGenericDefinition(CreatedType, typeof(List<>), out tempCollectionType) - || (IsArray && !IsMultidimensionalArray)) - { - ShouldCreateWrapper = true; - } - } -#endif - - if (CollectionItemType != null && - ImmutableCollectionsUtils.TryBuildImmutableForArrayContract( - NonNullableUnderlyingType, - CollectionItemType, - out var immutableCreatedType, - out var immutableParameterizedCreator)) - { - CreatedType = immutableCreatedType; - _parameterizedCreator = immutableParameterizedCreator; - IsReadOnlyOrFixedSize = true; - CanDeserialize = true; - } - } - - internal IWrappedCollection CreateWrapper(object list) - { - if (_genericWrapperCreator == null) - { - MiscellaneousUtils.Assert(_genericCollectionDefinitionType != null); - - _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType); - - Type constructorArgument; - - if (ReflectionUtils.InheritsGenericDefinition(_genericCollectionDefinitionType, typeof(List<>)) - || _genericCollectionDefinitionType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - constructorArgument = typeof(ICollection<>).MakeGenericType(CollectionItemType); - else - constructorArgument = _genericCollectionDefinitionType; - - var genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { constructorArgument }); - _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(genericWrapperConstructor); - } - - return (IWrappedCollection)_genericWrapperCreator(list); - } - - internal IList CreateTemporaryCollection() - { - if (_genericTemporaryCollectionCreator == null) - { - // multidimensional array will also have array instances in it - var collectionItemType = IsMultidimensionalArray || CollectionItemType == null - ? typeof(object) - : CollectionItemType; - - var temporaryListType = typeof(List<>).MakeGenericType(collectionItemType); - _genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(temporaryListType); - } - - return (IList)_genericTemporaryCollectionCreator(); - } - -#if HAVE_FSHARP_TYPES - private void StoreFSharpListCreatorIfNecessary(Type underlyingType) - { - if (!HasParameterizedCreatorInternal && underlyingType.Name == FSharpUtils.FSharpListTypeName) - { - FSharpUtils.EnsureInitialized(underlyingType.Assembly()); - _parameterizedCreator = FSharpUtils.Instance.CreateSeq(CollectionItemType!); - } - } -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContainerContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContainerContract.cs deleted file mode 100644 index 3f56b1ff3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContainerContract.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ - -#else - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonContainerContract : JsonContract - { - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - internal JsonContainerContract(Type underlyingType) - : base(underlyingType) - { - var jsonContainerAttribute = JsonTypeReflector.GetCachedAttribute(underlyingType); - - if (jsonContainerAttribute != null) - { - if (jsonContainerAttribute.ItemConverterType != null) - { - ItemConverter = JsonTypeReflector.CreateJsonConverterInstance( - jsonContainerAttribute.ItemConverterType, - jsonContainerAttribute.ItemConverterParameters); - } - - ItemIsReference = jsonContainerAttribute._itemIsReference; - ItemReferenceLoopHandling = jsonContainerAttribute._itemReferenceLoopHandling; - ItemTypeNameHandling = jsonContainerAttribute._itemTypeNameHandling; - } - } - - private JsonContract? _itemContract; - - // the final (i.e. can't be inherited from like a sealed class or valuetype) item contract - internal JsonContract? FinalItemContract { get; private set; } - - // will be null for containers that don't have an item type (e.g. IList) or for complex objects - internal JsonContract? ItemContract - { - get => _itemContract; - set - { - _itemContract = value; - if (_itemContract != null) - FinalItemContract = _itemContract.UnderlyingType.IsSealed() ? _itemContract : null; - else - FinalItemContract = null; - } - } - - /// - /// Gets or sets the default collection items . - /// - /// The converter. - public JsonConverter? ItemConverter { get; set; } - - /// - /// Gets or sets a value indicating whether the collection items preserve object references. - /// - /// true if collection items preserve object references; otherwise, false. - public bool? ItemIsReference { get; set; } - - /// - /// Gets or sets the collection item reference loop handling. - /// - /// The reference loop handling. - public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } - - /// - /// Gets or sets the collection item type name handling. - /// - /// The type name handling. - public TypeNameHandling? ItemTypeNameHandling { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContract.cs deleted file mode 100644 index 6102bdf58..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonContract.cs +++ /dev/null @@ -1,297 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal enum JsonContractType - { - None = 0, - Object = 1, - Array = 2, - Primitive = 3, - String = 4, - Dictionary = 5, - Dynamic = 6, - Serializable = 7, - Linq = 8 - } - - /// - /// Handles serialization callback events. - /// - /// The object that raised the callback event. - /// The streaming context. - internal delegate void SerializationCallback(object o, StreamingContext context); - - /// - /// Handles serialization error callback events. - /// - /// The object that raised the callback event. - /// The streaming context. - /// The error context. - internal delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext); - - /// - /// Sets extension data for an object during deserialization. - /// - /// The object to set extension data on. - /// The extension data key. - /// The extension data value. - internal delegate void ExtensionDataSetter(object o, string key, object? value); - - /// - /// Gets extension data for an object during serialization. - /// - /// The object to set extension data on. - internal delegate IEnumerable>? ExtensionDataGetter(object o); - - /// - /// Contract details for a used by the . - /// - internal abstract class JsonContract - { - internal JsonContract(Type underlyingType) - { - ValidationUtils.ArgumentNotNull(underlyingType, nameof(underlyingType)); - - UnderlyingType = underlyingType; - - // resolve ByRef types - // typically comes from in and ref parameters on methods/ctors - underlyingType = ReflectionUtils.EnsureNotByRefType(underlyingType); - - IsNullable = ReflectionUtils.IsNullable(underlyingType); - - NonNullableUnderlyingType = IsNullable && ReflectionUtils.IsNullableType(underlyingType) - ? Nullable.GetUnderlyingType(underlyingType) - : underlyingType; - - _createdType = CreatedType = NonNullableUnderlyingType; - - IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType); - IsEnum = NonNullableUnderlyingType.IsEnum(); - - InternalReadType = ReadType.Read; - } - - private Type _createdType; - - private List? _onDeserializedCallbacks; - private List? _onDeserializingCallbacks; - private List? _onErrorCallbacks; - private List? _onSerializedCallbacks; - private List? _onSerializingCallbacks; - internal JsonContractType ContractType; - - /// - /// Gets or sets the default for this contract. - /// - /// The converter. - public JsonConverter? Converter { get; set; } - - /// - /// Gets or sets the type created during deserialization. - /// - /// The type created during deserialization. - public Type CreatedType - { - get => _createdType; - set - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - _createdType = value; - - IsSealed = _createdType.IsSealed(); - IsInstantiable = !(_createdType.IsInterface() || _createdType.IsAbstract()); - } - } - - /// - /// Gets or sets the default creator method used to create the object. - /// - /// The default creator method used to create the object. - public Func? DefaultCreator { get; set; } - - /// - /// Gets or sets a value indicating whether the default creator is non-public. - /// - /// true if the default object creator is non-public; otherwise, false. - public bool DefaultCreatorNonPublic { get; set; } - - /// - /// Gets the internally resolved for the contract's type. - /// This converter is used as a fallback converter when no other converter is resolved. - /// Setting will always override this converter. - /// - public JsonConverter? InternalConverter { get; internal set; } - - internal ReadType InternalReadType; - internal bool IsConvertable; - internal bool IsEnum; - internal bool IsInstantiable; - internal bool IsNullable; - internal bool IsReadOnlyOrFixedSize; - - /// - /// Gets or sets whether this type contract is serialized as a reference. - /// - /// Whether this type contract is serialized as a reference. - public bool? IsReference { get; set; } - - internal bool IsSealed; - internal Type NonNullableUnderlyingType; - - /// - /// Gets or sets all methods called immediately after deserialization of the object. - /// - /// The methods called immediately after deserialization of the object. - public IList OnDeserializedCallbacks - { - get - { - if (_onDeserializedCallbacks == null) _onDeserializedCallbacks = new List(); - - return _onDeserializedCallbacks; - } - } - - /// - /// Gets or sets all methods called during deserialization of the object. - /// - /// The methods called during deserialization of the object. - public IList OnDeserializingCallbacks - { - get - { - if (_onDeserializingCallbacks == null) _onDeserializingCallbacks = new List(); - - return _onDeserializingCallbacks; - } - } - - /// - /// Gets or sets all method called when an error is thrown during the serialization of the object. - /// - /// The methods called when an error is thrown during the serialization of the object. - public IList OnErrorCallbacks - { - get - { - if (_onErrorCallbacks == null) _onErrorCallbacks = new List(); - - return _onErrorCallbacks; - } - } - - /// - /// Gets or sets all methods called after serialization of the object graph. - /// - /// The methods called after serialization of the object graph. - public IList OnSerializedCallbacks - { - get - { - if (_onSerializedCallbacks == null) _onSerializedCallbacks = new List(); - - return _onSerializedCallbacks; - } - } - - /// - /// Gets or sets all methods called before serialization of the object. - /// - /// The methods called before serialization of the object. - public IList OnSerializingCallbacks - { - get - { - if (_onSerializingCallbacks == null) _onSerializingCallbacks = new List(); - - return _onSerializingCallbacks; - } - } - - /// - /// Gets the underlying type for the contract. - /// - /// The underlying type for the contract. - public Type UnderlyingType { get; } - - internal void InvokeOnSerializing(object o, StreamingContext context) - { - if (_onSerializingCallbacks != null) - { - foreach (var callback in _onSerializingCallbacks) callback(o, context); - } - } - - internal void InvokeOnSerialized(object o, StreamingContext context) - { - if (_onSerializedCallbacks != null) - { - foreach (var callback in _onSerializedCallbacks) callback(o, context); - } - } - - internal void InvokeOnDeserializing(object o, StreamingContext context) - { - if (_onDeserializingCallbacks != null) - { - foreach (var callback in _onDeserializingCallbacks) callback(o, context); - } - } - - internal void InvokeOnDeserialized(object o, StreamingContext context) - { - if (_onDeserializedCallbacks != null) - { - foreach (var callback in _onDeserializedCallbacks) callback(o, context); - } - } - - internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext) - { - if (_onErrorCallbacks != null) - { - foreach (var callback in _onErrorCallbacks) callback(o, context, errorContext); - } - } - - internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo) => - (o, context) => callbackMethodInfo.Invoke(o, new object[] { context }); - - internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo) => - (o, context, econtext) => callbackMethodInfo.Invoke(o, new object[] { context, econtext }); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs deleted file mode 100644 index 226f7cf2d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs +++ /dev/null @@ -1,234 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonDictionaryContract : JsonContainerContract - { - private readonly Type? _genericCollectionDefinitionType; - - private readonly ConstructorInfo? _parameterizedConstructor; - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonDictionaryContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Dictionary; - - Type? keyType; - Type? valueType; - - if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType)) - { - keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; - valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; - - if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<,>))) - CreatedType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); - else if (NonNullableUnderlyingType.IsGenericType()) - { - // ConcurrentDictionary<,> + IDictionary setter + null value = error - // wrap to use generic setter - // https://github.com/JamesNK/Newtonsoft.Json/issues/1582 - var typeDefinition = NonNullableUnderlyingType.GetGenericTypeDefinition(); - if (typeDefinition.FullName == JsonTypeReflector.ConcurrentDictionaryTypeName) ShouldCreateWrapper = true; - } - -#if HAVE_READ_ONLY_COLLECTIONS - IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyDictionary<,>)); -#endif - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<,>), out _genericCollectionDefinitionType)) - { - keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; - valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; - - if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<,>))) - { - CreatedType = typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType); - } - - IsReadOnlyOrFixedSize = true; - } -#endif - else - { - ReflectionUtils.GetDictionaryKeyValueTypes(NonNullableUnderlyingType, out keyType, out valueType); - - if (NonNullableUnderlyingType == typeof(IDictionary)) CreatedType = typeof(Dictionary); - } - - if (keyType != null && valueType != null) - { - _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor( - CreatedType, - typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType), - typeof(IDictionary<,>).MakeGenericType(keyType, valueType)); - -#if HAVE_FSHARP_TYPES - if (!HasParameterizedCreatorInternal && NonNullableUnderlyingType.Name == FSharpUtils.FSharpMapTypeName) - { - FSharpUtils.EnsureInitialized(NonNullableUnderlyingType.Assembly()); - _parameterizedCreator = FSharpUtils.Instance.CreateMap(keyType, valueType); - } -#endif - } - - if (!typeof(IDictionary).IsAssignableFrom(CreatedType)) ShouldCreateWrapper = true; - - DictionaryKeyType = keyType; - DictionaryValueType = valueType; - -#if (NET20 || NET35) - if (DictionaryValueType != null && ReflectionUtils.IsNullableType(DictionaryValueType)) - { - // bug in .NET 2.0 & 3.5 that Dictionary> throws an error when adding null via IDictionary[key] = object - // wrapper will handle calling Add(T) instead - if (ReflectionUtils.InheritsGenericDefinition(CreatedType, typeof(Dictionary<,>), out _)) - { - ShouldCreateWrapper = true; - } - } -#endif - - if (DictionaryKeyType != null && - DictionaryValueType != null && - ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract( - NonNullableUnderlyingType, - DictionaryKeyType, - DictionaryValueType, - out var immutableCreatedType, - out var immutableParameterizedCreator)) - { - CreatedType = immutableCreatedType; - _parameterizedCreator = immutableParameterizedCreator; - IsReadOnlyOrFixedSize = true; - } - } - - private Func? _genericTemporaryDictionaryCreator; - private ObjectConstructor? _genericWrapperCreator; - - private Type? _genericWrapperType; - - private ObjectConstructor? _parameterizedCreator; - - /// - /// Gets or sets the dictionary key resolver. - /// - /// The dictionary key resolver. - public Func? DictionaryKeyResolver { get; set; } - - /// - /// Gets the of the dictionary keys. - /// - /// The of the dictionary keys. - public Type? DictionaryKeyType { get; } - - /// - /// Gets the of the dictionary values. - /// - /// The of the dictionary values. - public Type? DictionaryValueType { get; } - - /// - /// Gets a value indicating whether the creator has a parameter with the dictionary values. - /// - /// true if the creator has a parameter with the dictionary values; otherwise, false. - public bool HasParameterizedCreator { get; set; } - - internal bool HasParameterizedCreatorInternal => - HasParameterizedCreator || _parameterizedCreator != null || _parameterizedConstructor != null; - - internal JsonContract? KeyContract { get; set; } - - /// - /// Gets or sets the function used to create the object. When set this function will override - /// . - /// - /// The function used to create the object. - public ObjectConstructor? OverrideCreator { get; set; } - - internal ObjectConstructor? ParameterizedCreator - { - get - { - if (_parameterizedCreator == null && _parameterizedConstructor != null) - _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); - - return _parameterizedCreator; - } - } - - internal bool ShouldCreateWrapper { get; } - - internal IWrappedDictionary CreateWrapper(object dictionary) - { - if (_genericWrapperCreator == null) - { - _genericWrapperType = typeof(DictionaryWrapper<,>).MakeGenericType(DictionaryKeyType, DictionaryValueType); - - var genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType! }); - _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(genericWrapperConstructor); - } - - return (IWrappedDictionary)_genericWrapperCreator(dictionary); - } - - internal IDictionary CreateTemporaryDictionary() - { - if (_genericTemporaryDictionaryCreator == null) - { - var temporaryDictionaryType = - typeof(Dictionary<,>).MakeGenericType(DictionaryKeyType ?? typeof(object), DictionaryValueType ?? typeof(object)); - - _genericTemporaryDictionaryCreator = - JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(temporaryDictionaryType); - } - - return (IDictionary)_genericTemporaryDictionaryCreator(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDynamicContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDynamicContract.cs deleted file mode 100644 index a465c3180..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonDynamicContract.cs +++ /dev/null @@ -1,119 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System; -using System.Dynamic; -using System.Runtime.CompilerServices; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonDynamicContract : JsonContainerContract - { - /// - /// Gets the object's properties. - /// - /// The object's properties. - public JsonPropertyCollection Properties { get; } - - /// - /// Gets or sets the property name resolver. - /// - /// The property name resolver. - public Func? PropertyNameResolver { get; set; } - - private readonly ThreadSafeStore>> _callSiteGetters = - new ThreadSafeStore>>(CreateCallSiteGetter); - - private readonly ThreadSafeStore>> _callSiteSetters = - new ThreadSafeStore>>(CreateCallSiteSetter); - - private static CallSite> CreateCallSiteGetter(string name) - { - GetMemberBinder getMemberBinder = (GetMemberBinder)DynamicUtils.BinderWrapper.GetMember(name, typeof(DynamicUtils)); - - return CallSite>.Create(new NoThrowGetBinderMember(getMemberBinder)); - } - - private static CallSite> CreateCallSiteSetter(string name) - { - SetMemberBinder binder = (SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils)); - - return CallSite>.Create(new NoThrowSetBinderMember(binder)); - } - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonDynamicContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Dynamic; - - Properties = new JsonPropertyCollection(UnderlyingType); - } - - internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object? value) - { - ValidationUtils.ArgumentNotNull(dynamicProvider, nameof(dynamicProvider)); - - CallSite> callSite = _callSiteGetters.Get(name); - - object result = callSite.Target(callSite, dynamicProvider); - - if (!ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult)) - { - value = result; - return true; - } - else - { - value = null; - return false; - } - } - - internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object? value) - { - ValidationUtils.ArgumentNotNull(dynamicProvider, nameof(dynamicProvider)); - - CallSite> callSite = _callSiteSetters.Get(name); - - object result = callSite.Target(callSite, dynamicProvider, value); - - return !ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs deleted file mode 100644 index 1282cd9cf..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs +++ /dev/null @@ -1,162 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BINARY_SERIALIZATION -using System; -using System.Globalization; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ -#pragma warning disable SYSLIB0050 - internal class JsonFormatterConverter : IFormatterConverter -#pragma warning restore SYSLIB0050 - { - private readonly JsonSerializerInternalReader _reader; - private readonly JsonISerializableContract _contract; - private readonly JsonProperty? _member; - - public JsonFormatterConverter(JsonSerializerInternalReader reader, JsonISerializableContract contract, JsonProperty? member) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - ValidationUtils.ArgumentNotNull(contract, nameof(contract)); - - _reader = reader; - _contract = contract; - _member = member; - } - - private T GetTokenValue(object value) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - JValue v = (JValue)value; - return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture); - } - - public object? Convert(object value, Type type) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - if (!(value is JToken token)) - { - throw new ArgumentException("Value is not a JToken.", nameof(value)); - } - - return _reader.CreateISerializableItem(token, type, _contract, _member); - } - - public object Convert(object value, TypeCode typeCode) - { - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - object? resolvedValue = (value is JValue v) ? v.Value : value; - - return System.Convert.ChangeType(resolvedValue, typeCode, CultureInfo.InvariantCulture); - } - - public bool ToBoolean(object value) - { - return GetTokenValue(value); - } - - public byte ToByte(object value) - { - return GetTokenValue(value); - } - - public char ToChar(object value) - { - return GetTokenValue(value); - } - - public DateTime ToDateTime(object value) - { - return GetTokenValue(value); - } - - public decimal ToDecimal(object value) - { - return GetTokenValue(value); - } - - public double ToDouble(object value) - { - return GetTokenValue(value); - } - - public short ToInt16(object value) - { - return GetTokenValue(value); - } - - public int ToInt32(object value) - { - return GetTokenValue(value); - } - - public long ToInt64(object value) - { - return GetTokenValue(value); - } - - public sbyte ToSByte(object value) - { - return GetTokenValue(value); - } - - public float ToSingle(object value) - { - return GetTokenValue(value); - } - - public string ToString(object value) - { - return GetTokenValue(value); - } - - public ushort ToUInt16(object value) - { - return GetTokenValue(value); - } - - public uint ToUInt32(object value) - { - return GetTokenValue(value); - } - - public ulong ToUInt64(object value) - { - return GetTokenValue(value); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonISerializableContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonISerializableContract.cs deleted file mode 100644 index 1fb764638..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonISerializableContract.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BINARY_SERIALIZATION -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonISerializableContract : JsonContainerContract - { - /// - /// Gets or sets the object constructor. - /// - /// The object constructor. - public ObjectConstructor? ISerializableCreator { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonISerializableContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Serializable; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonLinqContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonLinqContract.cs deleted file mode 100644 index dcb4e1b6a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonLinqContract.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonLinqContract : JsonContract - { - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonLinqContract(Type underlyingType) - : base(underlyingType) => - ContractType = JsonContractType.Linq; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonObjectContract.cs deleted file mode 100644 index 47dd88017..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonObjectContract.cs +++ /dev/null @@ -1,192 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.Runtime.Serialization; -using System.Security; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonObjectContract : JsonContainerContract - { - /// - /// Gets or sets the object member serialization. - /// - /// The member object serialization. - public MemberSerialization MemberSerialization { get; set; } - - /// - /// Gets or sets the missing member handling used when deserializing this object. - /// - /// The missing member handling. - public MissingMemberHandling? MissingMemberHandling { get; set; } - - /// - /// Gets or sets a value that indicates whether the object's properties are required. - /// - /// - /// A value indicating whether the object's properties are required. - /// - public Required? ItemRequired { get; set; } - - /// - /// Gets or sets how the object's properties with null values are handled during serialization and deserialization. - /// - /// How the object's properties with null values are handled during serialization and deserialization. - public NullValueHandling? ItemNullValueHandling { get; set; } - - /// - /// Gets the object's properties. - /// - /// The object's properties. - public JsonPropertyCollection Properties { get; } - - /// - /// Gets a collection of instances that define the parameters used with - /// . - /// - public JsonPropertyCollection CreatorParameters - { - get - { - if (_creatorParameters == null) _creatorParameters = new JsonPropertyCollection(UnderlyingType); - - return _creatorParameters; - } - } - - /// - /// Gets or sets the function used to create the object. When set this function will override - /// . - /// This function is called with a collection of arguments which are defined by the - /// collection. - /// - /// The function used to create the object. - public ObjectConstructor? OverrideCreator { get; set; } - - internal ObjectConstructor? ParameterizedCreator { get; set; } - - /// - /// Gets or sets the extension data setter. - /// - public ExtensionDataSetter? ExtensionDataSetter { get; set; } - - /// - /// Gets or sets the extension data getter. - /// - public ExtensionDataGetter? ExtensionDataGetter { get; set; } - - /// - /// Gets or sets the extension data value type. - /// - public Type? ExtensionDataValueType - { - get => _extensionDataValueType; - set - { - _extensionDataValueType = value; - ExtensionDataIsJToken = value != null && typeof(JToken).IsAssignableFrom(value); - } - } - - /// - /// Gets or sets the extension data name resolver. - /// - /// The extension data name resolver. - public Func? ExtensionDataNameResolver { get; set; } - - internal bool ExtensionDataIsJToken; - private bool? _hasRequiredOrDefaultValueProperties; - private JsonPropertyCollection? _creatorParameters; - private Type? _extensionDataValueType; - - internal bool HasRequiredOrDefaultValueProperties - { - get - { - if (_hasRequiredOrDefaultValueProperties == null) - { - _hasRequiredOrDefaultValueProperties = false; - - if (ItemRequired.GetValueOrDefault(Required.Default) != Required.Default) - _hasRequiredOrDefaultValueProperties = true; - else - { - foreach (var property in Properties) - { - if (property.Required != Required.Default || (property.DefaultValueHandling & DefaultValueHandling.Populate) - == DefaultValueHandling.Populate) - { - _hasRequiredOrDefaultValueProperties = true; - break; - } - } - } - } - - return _hasRequiredOrDefaultValueProperties.GetValueOrDefault(); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonObjectContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Object; - - Properties = new JsonPropertyCollection(UnderlyingType); - } - -#if HAVE_BINARY_FORMATTER -#if HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE - [SecuritySafeCritical] -#endif - internal object GetUninitializedObject() - { - // we should never get here if the environment is not fully trusted, check just in case - if (!JsonTypeReflector.FullyTrusted) - { - throw new JsonException("Insufficient permissions. Creating an uninitialized '{0}' type requires full trust.".FormatWith(CultureInfo.InvariantCulture, NonNullableUnderlyingType)); - } - -#pragma warning disable SYSLIB0050 - return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType); -#pragma warning restore SYSLIB0050 - } -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs deleted file mode 100644 index ec50a6bba..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs +++ /dev/null @@ -1,75 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonPrimitiveContract : JsonContract - { - private static readonly Dictionary ReadTypeMap = new() - { - [typeof(byte[])] = ReadType.ReadAsBytes, - [typeof(byte)] = ReadType.ReadAsInt32, - [typeof(short)] = ReadType.ReadAsInt32, - [typeof(int)] = ReadType.ReadAsInt32, - [typeof(decimal)] = ReadType.ReadAsDecimal, - [typeof(bool)] = ReadType.ReadAsBoolean, - [typeof(string)] = ReadType.ReadAsString, - [typeof(DateTime)] = ReadType.ReadAsDateTime, -#if HAVE_DATE_TIME_OFFSET - [typeof(DateTimeOffset)] = ReadType.ReadAsDateTimeOffset, -#endif - [typeof(float)] = ReadType.ReadAsDouble, - [typeof(double)] = ReadType.ReadAsDouble, - [typeof(long)] = ReadType.ReadAsInt64 - }; - - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonPrimitiveContract(Type underlyingType) - : base(underlyingType) - { - ContractType = JsonContractType.Primitive; - - TypeCode = ConvertUtils.GetTypeCode(underlyingType); - IsReadOnlyOrFixedSize = true; - - if (ReadTypeMap.TryGetValue(NonNullableUnderlyingType, out var readType)) InternalReadType = readType; - } - - internal PrimitiveTypeCode TypeCode { get; set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonProperty.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonProperty.cs deleted file mode 100644 index adcf0615e..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonProperty.cs +++ /dev/null @@ -1,308 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Maps a JSON property to a .NET member or constructor parameter. - /// - internal class JsonProperty - { - private object? _defaultValue; - internal bool _hasExplicitDefaultValue; - private bool _hasGeneratedDefaultValue; - private string? _propertyName; - private Type? _propertyType; - internal Required? _required; - internal bool _skipPropertyNameEscape; - - /// - /// Gets or sets the for this property. - /// - /// The for this property. - public IAttributeProvider? AttributeProvider { get; set; } - - /// - /// Gets or sets the for the property. - /// If set this converter takes precedence over the contract converter for the property type. - /// - /// The converter. - public JsonConverter? Converter { get; set; } - - /// - /// Gets or sets the type that declared this property. - /// - /// The type that declared this property. - public Type? DeclaringType { get; set; } - - /// - /// Gets the default value. - /// - /// The default value. - public object? DefaultValue - { - get - { - if (!_hasExplicitDefaultValue) return null; - - return _defaultValue; - } - set - { - _hasExplicitDefaultValue = true; - _defaultValue = value; - } - } - - /// - /// Gets or sets the property default value handling. - /// - /// The default value handling. - public DefaultValueHandling? DefaultValueHandling { get; set; } - - /// - /// Gets or sets a predicate used to determine whether the property should be serialized. - /// - /// A predicate used to determine whether the property should be serialized. - public Predicate? GetIsSpecified { get; set; } - - /// - /// Gets or sets a value indicating whether this has a member attribute. - /// - /// true if has a member attribute; otherwise, false. - public bool HasMemberAttribute { get; set; } - - /// - /// Gets or sets a value indicating whether this is ignored. - /// - /// true if ignored; otherwise, false. - public bool Ignored { get; set; } - - /// - /// Gets or sets a value indicating whether this property preserves object references. - /// - /// - /// true if this instance is reference; otherwise, false. - /// - public bool? IsReference { get; set; } - - /// - /// Gets a value indicating whether has a value specified. - /// - public bool IsRequiredSpecified => _required != null; - - /// - /// Gets or sets the converter used when serializing the property's collection items. - /// - /// The collection's items converter. - public JsonConverter? ItemConverter { get; set; } - - /// - /// Gets or sets whether this property's collection items are serialized as a reference. - /// - /// Whether this property's collection items are serialized as a reference. - public bool? ItemIsReference { get; set; } - - /// - /// Gets or sets the reference loop handling used when serializing the property's collection items. - /// - /// The collection's items reference loop handling. - public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } - - /// - /// Gets or sets the type name handling used when serializing the property's collection items. - /// - /// The collection's items type name handling. - public TypeNameHandling? ItemTypeNameHandling { get; set; } - - /// - /// Gets or sets the member converter. - /// - /// The member converter. - [Obsolete("MemberConverter is obsolete. Use Converter instead.")] - public JsonConverter? MemberConverter - { - get => Converter; - set => Converter = value; - } - - /// - /// Gets or sets the property null value handling. - /// - /// The null value handling. - public NullValueHandling? NullValueHandling { get; set; } - - /// - /// Gets or sets the property object creation handling. - /// - /// The object creation handling. - public ObjectCreationHandling? ObjectCreationHandling { get; set; } - - /// - /// Gets or sets the order of serialization of a member. - /// - /// The numeric order of serialization. - public int? Order { get; set; } - - // use to cache contract during deserialization - internal JsonContract? PropertyContract { get; set; } - - /// - /// Gets or sets the name of the property. - /// - /// The name of the property. - public string? PropertyName - { - get => _propertyName; - set - { - _propertyName = value; - _skipPropertyNameEscape = !JavaScriptUtils.ShouldEscapeJavaScriptString(_propertyName, JavaScriptUtils.HtmlCharEscapeFlags); - } - } - - /// - /// Gets or sets the type of the property. - /// - /// The type of the property. - public Type? PropertyType - { - get => _propertyType; - set - { - if (_propertyType != value) - { - _propertyType = value; - _hasGeneratedDefaultValue = false; - } - } - } - - /// - /// Gets or sets a value indicating whether this is readable. - /// - /// true if readable; otherwise, false. - public bool Readable { get; set; } - - /// - /// Gets or sets the property reference loop handling. - /// - /// The reference loop handling. - public ReferenceLoopHandling? ReferenceLoopHandling { get; set; } - - /// - /// Gets or sets a value indicating whether this is required. - /// - /// A value indicating whether this is required. - public Required Required - { - get => _required ?? Required.Default; - set => _required = value; - } - - /// - /// Gets or sets an action used to set whether the property has been deserialized. - /// - /// An action used to set whether the property has been deserialized. - public Action? SetIsSpecified { get; set; } - - /// - /// Gets or sets a predicate used to determine whether the property should be deserialized. - /// - /// A predicate used to determine whether the property should be deserialized. - public Predicate? ShouldDeserialize { get; set; } - - /// - /// Gets or sets a predicate used to determine whether the property should be serialized. - /// - /// A predicate used to determine whether the property should be serialized. - public Predicate? ShouldSerialize { get; set; } - - /// - /// Gets or sets or sets the type name handling. - /// - /// The type name handling. - public TypeNameHandling? TypeNameHandling { get; set; } - - /// - /// Gets or sets the name of the underlying member or parameter. - /// - /// The name of the underlying member or parameter. - public string? UnderlyingName { get; set; } - - /// - /// Gets the that will get and set the during serialization. - /// - /// The that will get and set the during serialization. - public IValueProvider? ValueProvider { get; set; } - - /// - /// Gets or sets a value indicating whether this is writable. - /// - /// true if writable; otherwise, false. - public bool Writable { get; set; } - - internal object? GetResolvedDefaultValue() - { - if (_propertyType == null) return null; - - if (!_hasExplicitDefaultValue && !_hasGeneratedDefaultValue) - { - _defaultValue = ReflectionUtils.GetDefaultValue(_propertyType); - _hasGeneratedDefaultValue = true; - } - - return _defaultValue; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() => PropertyName ?? string.Empty; - - internal void WritePropertyName(JsonWriter writer) - { - var propertyName = PropertyName; - MiscellaneousUtils.Assert(propertyName != null); - - if (_skipPropertyNameEscape) - writer.WritePropertyName(propertyName, false); - else - writer.WritePropertyName(propertyName); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs deleted file mode 100644 index b501bec6f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs +++ /dev/null @@ -1,176 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// A collection of objects. - /// - internal class JsonPropertyCollection : KeyedCollection - { - private readonly List _list; - private readonly Type _type; - - /// - /// Initializes a new instance of the class. - /// - /// The type. - public JsonPropertyCollection(Type type) - : base(StringComparer.Ordinal) - { - ValidationUtils.ArgumentNotNull(type, "type"); - _type = type; - - // foreach over List to avoid boxing the Enumerator - _list = (List)Items; - } - - /// - /// When implemented in a derived class, extracts the key from the specified element. - /// - /// The element from which to extract the key. - /// The key for the specified element. - protected override string GetKeyForItem(JsonProperty item) => item.PropertyName!; - - /// - /// Adds a object. - /// - /// The property to add to the collection. - public void AddProperty(JsonProperty property) - { - MiscellaneousUtils.Assert(property.PropertyName != null); - - if (Contains(property.PropertyName)) - { - // don't overwrite existing property with ignored property - if (property.Ignored) return; - - var existingProperty = this[property.PropertyName]; - var duplicateProperty = true; - - if (existingProperty.Ignored) - { - // remove ignored property so it can be replaced in collection - Remove(existingProperty); - duplicateProperty = false; - } - else - { - if (property.DeclaringType != null && existingProperty.DeclaringType != null) - { - if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType) - || existingProperty.DeclaringType.IsInterface() - && property.DeclaringType.ImplementInterface(existingProperty.DeclaringType)) - { - // current property is on a derived class and hides the existing - Remove(existingProperty); - duplicateProperty = false; - } - if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType) - || property.DeclaringType.IsInterface() && existingProperty.DeclaringType.ImplementInterface(property.DeclaringType)) - { - // current property is hidden by the existing so don't add it - return; - } - - if (_type.ImplementInterface(existingProperty.DeclaringType) && _type.ImplementInterface(property.DeclaringType)) - { - // current property was already defined on another interface - return; - } - } - } - - if (duplicateProperty) - throw new JsonSerializationException( - "A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith( - CultureInfo.InvariantCulture, property.PropertyName, _type)); - } - - Add(property); - } - - /// - /// Gets the closest matching object. - /// First attempts to get an exact case match of and then - /// a case insensitive match. - /// - /// Name of the property. - /// A matching property if found. - public JsonProperty? GetClosestMatchProperty(string propertyName) - { - var property = GetProperty(propertyName, StringComparison.Ordinal); - if (property == null) property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); - - return property; - } - - private bool TryGetValue(string key, [NotNullWhen(true)] out JsonProperty? item) - { - if (Dictionary == null) - { - item = default; - return false; - } - - return Dictionary.TryGetValue(key, out item); - } - - /// - /// Gets a property by property name. - /// - /// The name of the property to get. - /// Type property name string comparison. - /// A matching property if found. - public JsonProperty? GetProperty(string propertyName, StringComparison comparisonType) - { - // KeyedCollection has an ordinal comparer - if (comparisonType == StringComparison.Ordinal) - { - if (TryGetValue(propertyName, out var property)) return property; - - return null; - } - - for (var i = 0; i < _list.Count; i++) - { - var property = _list[i]; - if (string.Equals(propertyName, property.PropertyName, comparisonType)) return property; - } - - return null; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs deleted file mode 100644 index eb8b97a2e..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs +++ /dev/null @@ -1,140 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal abstract class JsonSerializerInternalBase - { - internal readonly JsonSerializer Serializer; - internal readonly ITraceWriter? TraceWriter; - - protected JsonSerializerInternalBase(JsonSerializer serializer) - { - ValidationUtils.ArgumentNotNull(serializer, nameof(serializer)); - - Serializer = serializer; - TraceWriter = serializer.TraceWriter; - } - - private ErrorContext? _currentErrorContext; - private BidirectionalDictionary? _mappings; - - internal BidirectionalDictionary DefaultReferenceMappings - { - get - { - // override equality comparer for object key dictionary - // object will be modified as it deserializes and might have mutable hashcode - if (_mappings == null) - { - _mappings = new BidirectionalDictionary( - EqualityComparer.Default, - new ReferenceEqualsEqualityComparer(), - "A different value already has the Id '{0}'.", - "A different Id has already been assigned for value '{0}'. This error may be caused by an object being reused multiple times during deserialization and can be fixed with the setting ObjectCreationHandling.Replace."); - } - - return _mappings; - } - } - - protected JsonSerializerProxy? InternalSerializer; - - protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract? containerContract, JsonProperty property) - { - var resolvedNullValueHandling = - property.NullValueHandling - ?? containerContract?.ItemNullValueHandling - ?? Serializer._nullValueHandling; - - return resolvedNullValueHandling; - } - - private ErrorContext GetErrorContext(object? currentObject, object? member, string path, Exception error) - { - if (_currentErrorContext == null) _currentErrorContext = new ErrorContext(currentObject, member, path, error); - - if (_currentErrorContext.Error != error) - throw new InvalidOperationException("Current error context error is different to requested error."); - - return _currentErrorContext; - } - - protected void ClearErrorContext() - { - if (_currentErrorContext == null) throw new InvalidOperationException("Could not clear error context. Error context is already null."); - - _currentErrorContext = null; - } - - protected bool IsErrorHandled(object? currentObject, JsonContract? contract, object? keyValue, IJsonLineInfo? lineInfo, string path, - Exception ex - ) - { - var errorContext = GetErrorContext(currentObject, keyValue, path, ex); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Error && !errorContext.Traced) - { - // only write error once - errorContext.Traced = true; - - // kind of a hack but meh. might clean this up later - var message = GetType() == typeof(JsonSerializerInternalWriter) ? "Error serializing" : "Error deserializing"; - if (contract != null) message += " " + contract.UnderlyingType; - message += ". " + ex.Message; - - // add line information to non-json.net exception message - if (!(ex is JsonException)) message = JsonPosition.FormatMessage(lineInfo, path, message); - - TraceWriter.Trace(TraceLevel.Error, message, ex); - } - - // attribute method is non-static so don't invoke if no object - if (contract != null && currentObject != null) contract.InvokeOnError(currentObject, Serializer.Context, errorContext); - - if (!errorContext.Handled) Serializer.OnError(new ErrorEventArgs(currentObject, errorContext)); - - return errorContext.Handled; - } - - private class ReferenceEqualsEqualityComparer : IEqualityComparer - { - bool IEqualityComparer.Equals(object x, object y) => ReferenceEquals(x, y); - - int IEqualityComparer.GetHashCode(object obj) => - // put objects in a bucket based on their reference - RuntimeHelpers.GetHashCode(obj); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs deleted file mode 100644 index ade850b08..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ /dev/null @@ -1,2392 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System.Dynamic; -#endif -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.Serialization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class JsonSerializerInternalReader : JsonSerializerInternalBase - { - internal enum PropertyPresence - { - None = 0, - Null = 1, - Value = 2 - } - - public JsonSerializerInternalReader(JsonSerializer serializer) - : base(serializer) { } - - public void Populate(JsonReader reader, object target) - { - ValidationUtils.ArgumentNotNull(target, nameof(target)); - - var objectType = target.GetType(); - - var contract = Serializer._contractResolver.ResolveContract(objectType); - - if (!reader.MoveToContent()) throw JsonSerializationException.Create(reader, "No JSON content found."); - - if (reader.TokenType == JsonToken.StartArray) - { - if (contract.ContractType == JsonContractType.Array) - { - var arrayContract = (JsonArrayContract)contract; - - PopulateList(arrayContract.ShouldCreateWrapper ? arrayContract.CreateWrapper(target) : (IList)target, reader, arrayContract, null, - null); - } - else - throw JsonSerializationException.Create(reader, - "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - else if (reader.TokenType == JsonToken.StartObject) - { - reader.ReadAndAssert(); - - string? id = null; - if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore - && reader.TokenType == JsonToken.PropertyName - && string.Equals(reader.Value!.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - id = reader.Value?.ToString(); - reader.ReadAndAssert(); - } - - if (contract.ContractType == JsonContractType.Dictionary) - { - var dictionaryContract = (JsonDictionaryContract)contract; - PopulateDictionary(dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(target) : (IDictionary)target, - reader, dictionaryContract, null, id); - } - else if (contract.ContractType == JsonContractType.Object) - PopulateObject(target, reader, (JsonObjectContract)contract, null, id); - else - throw JsonSerializationException.Create(reader, - "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - else - throw JsonSerializationException.Create(reader, - "Unexpected initial token '{0}' when populating object. Expected JSON object or array.".FormatWith(CultureInfo.InvariantCulture, - reader.TokenType)); - } - - private JsonContract? GetContractSafe(Type? type) - { - if (type == null) return null; - - return GetContract(type); - } - - private JsonContract GetContract(Type type) => Serializer._contractResolver.ResolveContract(type); - - public object? Deserialize(JsonReader reader, Type? objectType, bool checkAdditionalContent) - { - if (reader == null) throw new ArgumentNullException(nameof(reader)); - - var contract = GetContractSafe(objectType); - - try - { - var converter = GetConverter(contract, null, null, null); - - if (reader.TokenType == JsonToken.None && !reader.ReadForType(contract, converter != null)) - { - if (contract != null && !contract.IsNullable) - throw JsonSerializationException.Create(reader, - "No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, - contract.UnderlyingType)); - - return null; - } - - object? deserializedValue; - - if (converter != null && converter.CanRead) - deserializedValue = DeserializeConvertable(converter, reader, objectType!, null); - else - deserializedValue = CreateValueInternal(reader, objectType, contract, null, null, null, null); - - if (checkAdditionalContent) - { - while (reader.Read()) - if (reader.TokenType != JsonToken.Comment) - throw JsonSerializationException.Create(reader, - "Additional text found in JSON string after finishing deserializing object."); - } - - return deserializedValue; - } - catch (Exception ex) - { - if (IsErrorHandled(null, contract, null, reader as IJsonLineInfo, reader.Path, ex)) - { - HandleError(reader, false, 0); - return null; - } - // clear context in case serializer is being used inside a converter - // if the converter wraps the error then not clearing the context will cause this error: - // "Current error context error is different to requested error." - ClearErrorContext(); - throw; - } - } - - private JsonSerializerProxy GetInternalSerializer() - { - if (InternalSerializer == null) InternalSerializer = new JsonSerializerProxy(this); - - return InternalSerializer; - } - - private JToken? CreateJToken(JsonReader reader, JsonContract? contract) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - if (contract != null) - { - if (contract.UnderlyingType == typeof(JRaw)) return JRaw.Create(reader); - - if (reader.TokenType == JsonToken.Null - && !(contract.UnderlyingType == typeof(JValue) || contract.UnderlyingType == typeof(JToken))) - return null; - } - - JToken? token; - using (var writer = new JTokenWriter()) - { - writer.WriteToken(reader); - token = writer.Token; - } - - if (contract != null && token != null) - { - if (!contract.UnderlyingType.IsAssignableFrom(token.GetType())) - { - throw JsonSerializationException.Create(reader, "Deserialized JSON type '{0}' is not compatible with expected type '{1}'." - .FormatWith(CultureInfo.InvariantCulture, token.GetType().FullName, contract.UnderlyingType.FullName)); - } - } - - return token; - } - - private JToken CreateJObject(JsonReader reader) - { - ValidationUtils.ArgumentNotNull(reader, nameof(reader)); - - // this is needed because we've already read inside the object, looking for metadata properties - using (var writer = new JTokenWriter()) - { - writer.WriteStartObject(); - - do - if (reader.TokenType == JsonToken.PropertyName) - { - var propertyName = (string)reader.Value!; - if (!reader.ReadAndMoveToContent()) break; - - if (CheckPropertyName(reader, propertyName)) continue; - - writer.WritePropertyName(propertyName); - writer.WriteToken(reader, true, true, false); - } - else if (reader.TokenType == JsonToken.Comment) - { - // eat - } - else - { - writer.WriteEndObject(); - return writer.Token!; - } - while (reader.Read()); - - throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); - } - } - - private object? CreateValueInternal(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue - ) - { - if (contract != null && contract.ContractType == JsonContractType.Linq) return CreateJToken(reader, contract); - - do - switch (reader.TokenType) - { - // populate a typed object or generic dictionary/array - // depending upon whether an objectType was supplied - case JsonToken.StartObject: - return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue); - case JsonToken.StartArray: - return CreateList(reader, objectType, contract, member, existingValue, null); - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.Boolean: - case JsonToken.Date: - case JsonToken.Bytes: - return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); - case JsonToken.String: - var s = (string)reader.Value!; - - // string that needs to be returned as a byte array should be base 64 decoded - if (objectType == typeof(byte[])) return Convert.FromBase64String(s); - - // convert empty string to null automatically for nullable types - if (CoerceEmptyStringToNull(objectType, contract, s)) return null; - - return EnsureType(reader, s, CultureInfo.InvariantCulture, contract, objectType); - case JsonToken.StartConstructor: - var constructorName = reader.Value!.ToString(); - - return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType); - case JsonToken.Null: - case JsonToken.Undefined: -#if HAVE_ADO_NET - if (objectType == typeof(DBNull)) - { - return DBNull.Value; - } -#endif - - return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); - case JsonToken.Raw: - return new JRaw((string?)reader.Value); - case JsonToken.Comment: - // ignore - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType); - } - while (reader.Read()); - - throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); - } - - private static bool CoerceEmptyStringToNull(Type? objectType, JsonContract? contract, string s) => StringUtils.IsNullOrEmpty(s) - && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable; - - internal string GetExpectedDescription(JsonContract contract) - { - switch (contract.ContractType) - { - case JsonContractType.Object: - case JsonContractType.Dictionary: -#if HAVE_BINARY_SERIALIZATION - case JsonContractType.Serializable: -#endif -#if HAVE_DYNAMIC - case JsonContractType.Dynamic: -#endif - return @"JSON object (e.g. {""name"":""value""})"; - case JsonContractType.Array: - return @"JSON array (e.g. [1,2,3])"; - case JsonContractType.Primitive: - return @"JSON primitive value (e.g. string, number, boolean, null)"; - case JsonContractType.String: - return @"JSON string value"; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private JsonConverter? GetConverter(JsonContract? contract, JsonConverter? memberConverter, JsonContainerContract? containerContract, - JsonProperty? containerProperty - ) - { - JsonConverter? converter = null; - if (memberConverter != null) - { - // member attribute converter - converter = memberConverter; - } - else if (containerProperty?.ItemConverter != null) - converter = containerProperty.ItemConverter; - else if (containerContract?.ItemConverter != null) - converter = containerContract.ItemConverter; - else if (contract != null) - { - if (contract.Converter != null) - { - // class attribute converter - converter = contract.Converter; - } - else if (Serializer.GetMatchingConverter(contract.UnderlyingType) is JsonConverter matchingConverter) - { - // passed in converters - converter = matchingConverter; - } - else if (contract.InternalConverter != null) - { - // internally specified converter - converter = contract.InternalConverter; - } - } - return converter; - } - - private object? CreateObject(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue - ) - { - string? id; - var resolvedObjectType = objectType; - - if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore) - { - // don't look for metadata properties - reader.ReadAndAssert(); - id = null; - } - else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) - { - if (!(reader is JTokenReader tokenReader)) - { - var t = JToken.ReadFrom(reader); - tokenReader = (JTokenReader)t.CreateReader(); - tokenReader.Culture = reader.Culture; - tokenReader.DateFormatString = reader.DateFormatString; - tokenReader.DateParseHandling = reader.DateParseHandling; - tokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; - tokenReader.FloatParseHandling = reader.FloatParseHandling; - tokenReader.SupportMultipleContent = reader.SupportMultipleContent; - - // start - tokenReader.ReadAndAssert(); - - reader = tokenReader; - } - - if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, - existingValue, out var newValue, out id)) return newValue; - } - else - { - reader.ReadAndAssert(); - if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, - out var newValue, out id)) return newValue; - } - - if (HasNoDefinedType(contract)) return CreateJObject(reader); - - MiscellaneousUtils.Assert(resolvedObjectType != null); - MiscellaneousUtils.Assert(contract != null); - - switch (contract.ContractType) - { - case JsonContractType.Object: - { - var createdFromNonDefaultCreator = false; - var objectContract = (JsonObjectContract)contract; - object targetObject; - // check that if type name handling is being used that the existing value is compatible with the specified type - if (existingValue != null && (resolvedObjectType == objectType || resolvedObjectType.IsAssignableFrom(existingValue.GetType()))) - targetObject = existingValue; - else - targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultCreator); - - // don't populate if read from non-default creator because the object has already been read - if (createdFromNonDefaultCreator) return targetObject; - - return PopulateObject(targetObject, reader, objectContract, member, id); - } - case JsonContractType.Primitive: - { - var primitiveContract = (JsonPrimitiveContract)contract; - // if the content is inside $value then read past it - if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore - && reader.TokenType == JsonToken.PropertyName - && string.Equals(reader.Value!.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - - // the token should not be an object because the $type value could have been included in the object - // without needing the $value property - if (reader.TokenType == JsonToken.StartObject) - throw JsonSerializationException.Create(reader, - "Unexpected token when deserializing primitive value: " + reader.TokenType); - - var value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue); - - reader.ReadAndAssert(); - return value; - } - break; - } - case JsonContractType.Dictionary: - { - var dictionaryContract = (JsonDictionaryContract)contract; - object targetDictionary; - - if (existingValue == null) - { - var dictionary = CreateNewDictionary(reader, dictionaryContract, out var createdFromNonDefaultCreator); - - if (createdFromNonDefaultCreator) - { - if (id != null) - throw JsonSerializationException.Create(reader, - "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}." - .FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (contract.OnSerializingCallbacks.Count > 0) - throw JsonSerializationException.Create(reader, - "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}." - .FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (contract.OnErrorCallbacks.Count > 0) - throw JsonSerializationException.Create(reader, - "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (!dictionaryContract.HasParameterizedCreatorInternal) - throw JsonSerializationException.Create(reader, - "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, - contract.UnderlyingType)); - } - - PopulateDictionary(dictionary, reader, dictionaryContract, member, id); - - if (createdFromNonDefaultCreator) - { - var creator = (dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator)!; - - return creator(dictionary); - } - if (dictionary is IWrappedDictionary wrappedDictionary) return wrappedDictionary.UnderlyingDictionary; - - targetDictionary = dictionary; - } - else - targetDictionary = - PopulateDictionary( - dictionaryContract.ShouldCreateWrapper || !(existingValue is IDictionary) - ? dictionaryContract.CreateWrapper(existingValue) - : (IDictionary)existingValue, reader, dictionaryContract, member, id); - - return targetDictionary; - } -#if HAVE_DYNAMIC - case JsonContractType.Dynamic: - JsonDynamicContract dynamicContract = (JsonDynamicContract)contract; - return CreateDynamic(reader, dynamicContract, member, id); -#endif -#if HAVE_BINARY_SERIALIZATION - case JsonContractType.Serializable: - JsonISerializableContract serializableContract = (JsonISerializableContract)contract; - return CreateISerializable(reader, serializableContract, member, id); -#endif - } - - var message = - @"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly." - + Environment.NewLine + - @"To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." - + Environment.NewLine; - message = message.FormatWith(CultureInfo.InvariantCulture, resolvedObjectType, GetExpectedDescription(contract)); - - throw JsonSerializationException.Create(reader, message); - } - - private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id - ) - { - id = null; - newValue = null; - - if (reader.TokenType == JsonToken.StartObject) - { - var current = (JObject)reader.CurrentToken!; - - var refProperty = current.Property(JsonTypeReflector.RefPropertyName, StringComparison.Ordinal); - if (refProperty != null) - { - var refToken = refProperty.Value; - if (refToken.Type != JTokenType.String && refToken.Type != JTokenType.Null) - throw JsonSerializationException.Create(refToken, refToken.Path, - "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, - JsonTypeReflector.RefPropertyName), null); - - var reference = (string?)refProperty; - - if (reference != null) - { - var additionalContent = refProperty.Next ?? refProperty.Previous; - if (additionalContent != null) - throw JsonSerializationException.Create(additionalContent, additionalContent.Path, - "Additional content found in JSON reference object. A JSON reference object should only have a {0} property." - .FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null); - - newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader, reader.Path, - "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, - newValue.GetType())), null); - - reader.Skip(); - return true; - } - } - var typeToken = current[JsonTypeReflector.TypePropertyName]; - if (typeToken != null) - { - var qualifiedTypeName = (string?)typeToken; - var typeTokenReader = typeToken.CreateReader(); - typeTokenReader.ReadAndAssert(); - ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName!); - - var valueToken = current[JsonTypeReflector.ValuePropertyName]; - if (valueToken != null) - { - while (true) - { - reader.ReadAndAssert(); - if (reader.TokenType == JsonToken.PropertyName) - if ((string)reader.Value! == JsonTypeReflector.ValuePropertyName) - return false; - - reader.ReadAndAssert(); - reader.Skip(); - } - } - } - var idToken = current[JsonTypeReflector.IdPropertyName]; - if (idToken != null) id = (string?)idToken; - var valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName]; - if (valuesToken != null) - { - var listReader = valuesToken.CreateReader(); - listReader.ReadAndAssert(); - newValue = CreateList(listReader, objectType, contract, member, existingValue, id); - - reader.Skip(); - return true; - } - } - - reader.ReadAndAssert(); - return false; - } - - private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id - ) - { - id = null; - newValue = null; - - if (reader.TokenType == JsonToken.PropertyName) - { - var propertyName = reader.Value!.ToString(); - - if (propertyName.Length > 0 && propertyName[0] == '$') - { - // read metadata properties - // $type, $id, $ref, etc - bool metadataProperty; - - do - { - propertyName = reader.Value!.ToString(); - - if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null) - throw JsonSerializationException.Create(reader, - "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, - JsonTypeReflector.RefPropertyName)); - - var reference = reader.Value?.ToString(); - - reader.ReadAndAssert(); - - if (reference != null) - { - if (reader.TokenType == JsonToken.PropertyName) - throw JsonSerializationException.Create(reader, - "Additional content found in JSON reference object. A JSON reference object should only have a {0} property." - .FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName)); - - newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, - newValue!.GetType())), null); - - return true; - } - metadataProperty = true; - } - else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - var qualifiedTypeName = reader.Value!.ToString(); - - ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); - - reader.ReadAndAssert(); - - metadataProperty = true; - } - else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - - id = reader.Value?.ToString(); - - reader.ReadAndAssert(); - metadataProperty = true; - } - else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal)) - { - reader.ReadAndAssert(); - var list = CreateList(reader, objectType, contract, member, existingValue, id); - reader.ReadAndAssert(); - newValue = list; - return true; - } - else - metadataProperty = false; - } while (metadataProperty && reader.TokenType == JsonToken.PropertyName); - } - } - return false; - } - - private void ResolveTypeName(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerMember, string qualifiedTypeName - ) - { - var resolvedTypeNameHandling = - member?.TypeNameHandling - ?? containerContract?.ItemTypeNameHandling - ?? containerMember?.ItemTypeNameHandling - ?? Serializer._typeNameHandling; - - if (resolvedTypeNameHandling != TypeNameHandling.None) - { - var typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName); - - Type specifiedType; - try - { - specifiedType = Serializer._serializationBinder.BindToType(typeNameKey.Value1, typeNameKey.Value2); - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex); - } - - if (specifiedType == null) - throw JsonSerializationException.Create(reader, - "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName, specifiedType)), null); - - if (objectType != null -#if HAVE_DYNAMIC - && objectType != typeof(IDynamicMetaObjectProvider) -#endif - && !objectType.IsAssignableFrom(specifiedType)) - throw JsonSerializationException.Create(reader, - "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, - specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); - - objectType = specifiedType; - contract = GetContract(specifiedType); - } - } - - private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract) - { - if (contract == null) - throw JsonSerializationException.Create(reader, - "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType)); - - if (!(contract is JsonArrayContract arrayContract)) - { - var message = - @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly." - + Environment.NewLine + - @"To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array." - + Environment.NewLine; - message = message.FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)); - - throw JsonSerializationException.Create(reader, message); - } - - return arrayContract; - } - - private object? CreateList(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, object? existingValue, - string? id - ) - { - object? value; - - if (HasNoDefinedType(contract)) return CreateJToken(reader, contract); - - MiscellaneousUtils.Assert(objectType != null); - MiscellaneousUtils.Assert(contract != null); - - var arrayContract = EnsureArrayContract(reader, objectType, contract); - - if (existingValue == null) - { - var list = CreateNewList(reader, arrayContract, out var createdFromNonDefaultCreator); - - if (createdFromNonDefaultCreator) - { - if (id != null) - throw JsonSerializationException.Create(reader, - "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (contract.OnSerializingCallbacks.Count > 0) - throw JsonSerializationException.Create(reader, - "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (contract.OnErrorCallbacks.Count > 0) - throw JsonSerializationException.Create(reader, - "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - if (!arrayContract.HasParameterizedCreatorInternal && !arrayContract.IsArray) - throw JsonSerializationException.Create(reader, - "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - if (!arrayContract.IsMultidimensionalArray) - PopulateList(list, reader, arrayContract, member, id); - else - PopulateMultidimensionalArray(list, reader, arrayContract, member, id); - - if (createdFromNonDefaultCreator) - { - if (arrayContract.IsMultidimensionalArray) - list = CollectionUtils.ToMultidimensionalArray(list, arrayContract.CollectionItemType!, contract.CreatedType.GetArrayRank()); - else if (arrayContract.IsArray) - { - var a = Array.CreateInstance(arrayContract.CollectionItemType, list.Count); - list.CopyTo(a, 0); - list = a; - } - else - { - var creator = (arrayContract.OverrideCreator ?? arrayContract.ParameterizedCreator)!; - - return creator(list); - } - } - else if (list is IWrappedCollection wrappedCollection) return wrappedCollection.UnderlyingCollection; - - value = list; - } - else - { - if (!arrayContract.CanDeserialize) - throw JsonSerializationException.Create(reader, - "Cannot populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); - - value = PopulateList( - arrayContract.ShouldCreateWrapper || !(existingValue is IList list) ? arrayContract.CreateWrapper(existingValue) : list, reader, - arrayContract, member, id); - } - - return value; - } - - private bool HasNoDefinedType(JsonContract? contract) => - contract == null || contract.UnderlyingType == typeof(object) || contract.ContractType == JsonContractType.Linq; - - private object? EnsureType(JsonReader reader, object? value, CultureInfo culture, JsonContract? contract, Type? targetType) - { - if (targetType == null) return value; - - MiscellaneousUtils.Assert(contract != null); - var valueType = ReflectionUtils.GetObjectType(value); - - // type of value and type of target don't match - // attempt to convert value's type to target's type - if (valueType != targetType) - { - if (value == null && contract.IsNullable) return null; - - try - { - if (contract.IsConvertable) - { - var primitiveContract = (JsonPrimitiveContract)contract; - - if (contract.IsEnum) - { - if (value is string s) - { - return EnumUtils.ParseEnum( - contract.NonNullableUnderlyingType, - null, - s, - false); - } - if (ConvertUtils.IsInteger(primitiveContract.TypeCode)) return Enum.ToObject(contract.NonNullableUnderlyingType, value); - } - else if (contract.NonNullableUnderlyingType == typeof(DateTime)) - { - // use DateTimeUtils because Convert.ChangeType does not set DateTime.Kind correctly - if (value is string s && DateTimeUtils.TryParseDateTime(s, reader.DateTimeZoneHandling, reader.DateFormatString, - reader.Culture, out var dt)) return DateTimeUtils.EnsureDateTime(dt, reader.DateTimeZoneHandling); - } - -#if HAVE_BIG_INTEGER - if (value is BigInteger integer) - { - return ConvertUtils.FromBigInteger(integer, contract.NonNullableUnderlyingType); - } -#endif - - // this won't work when converting to a custom IConvertible - return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); - } - - return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType); - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(value), - targetType), ex); - } - } - - return value; - } - - private bool SetPropertyValue(JsonProperty property, JsonConverter? propertyConverter, JsonContainerContract? containerContract, - JsonProperty? containerProperty, JsonReader reader, object target - ) - { - var skipSettingProperty = CalculatePropertyDetails( - property, - ref propertyConverter, - containerContract, - containerProperty, - reader, - target, - out var useExistingValue, - out var currentValue, - out var propertyContract, - out var gottenCurrentValue, - out var ignoredValue); - - if (skipSettingProperty) - { - // Don't set extension data if the value was ignored - // e.g. a null with NullValueHandling should not go in ExtensionData - if (ignoredValue) return true; - - return false; - } - - object? value; - - if (propertyConverter != null && propertyConverter.CanRead) - { - if (!gottenCurrentValue && property.Readable) currentValue = property.ValueProvider!.GetValue(target); - - value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, currentValue); - } - else - value = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, - useExistingValue ? currentValue : null); - - // always set the value if useExistingValue is false, - // otherwise also set it if CreateValue returns a new value compared to the currentValue - // this could happen because of a JsonConverter against the type - if ((!useExistingValue || value != currentValue) - && ShouldSetPropertyValue(property, containerContract as JsonObjectContract, value)) - { - property.ValueProvider!.SetValue(target, value); - - if (property.SetIsSpecified != null) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, - property.DeclaringType)), null); - - property.SetIsSpecified(target, true); - } - - return true; - } - - // the value wasn't set be JSON was populated onto the existing value - return useExistingValue; - } - - private bool CalculatePropertyDetails( - JsonProperty property, - ref JsonConverter? propertyConverter, - JsonContainerContract? containerContract, - JsonProperty? containerProperty, - JsonReader reader, - object target, - out bool useExistingValue, - out object? currentValue, - out JsonContract? propertyContract, - out bool gottenCurrentValue, - out bool ignoredValue - ) - { - currentValue = null; - useExistingValue = false; - propertyContract = null; - gottenCurrentValue = false; - ignoredValue = false; - - if (property.Ignored) return true; - - var tokenType = reader.TokenType; - - if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); - - var objectCreationHandling = - property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling); - - if (objectCreationHandling != ObjectCreationHandling.Replace - && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject || propertyConverter != null) - && property.Readable) - { - currentValue = property.ValueProvider!.GetValue(target); - gottenCurrentValue = true; - - if (currentValue != null) - { - propertyContract = GetContract(currentValue.GetType()); - - useExistingValue = !propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType(); - } - } - - if (!property.Writable && !useExistingValue) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Unable to deserialize value to non-writable property '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, - property.PropertyName, property.DeclaringType)), null); - - return true; - } - - // test tokenType here because null might not be convertible to some types, e.g. ignoring null when applied to DateTime - if (tokenType == JsonToken.Null - && ResolvedNullValueHandling(containerContract as JsonObjectContract, property) == NullValueHandling.Ignore) - { - ignoredValue = true; - return true; - } - - // test tokenType here because default value might not be convertible to actual type, e.g. default of "" for DateTime - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) - && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) - && JsonTokenUtils.IsPrimitiveToken(tokenType) - && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue())) - { - ignoredValue = true; - return true; - } - - if (currentValue == null) - propertyContract = property.PropertyContract; - else - { - propertyContract = GetContract(currentValue.GetType()); - - if (propertyContract != property.PropertyContract) - propertyConverter = GetConverter(propertyContract, property.Converter, containerContract, containerProperty); - } - - return false; - } - - private void AddReference(JsonReader reader, string id, object value) - { - try - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Read object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, id, value.GetType())), null); - - Serializer.GetReferenceResolver().AddReference(this, id, value); - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, "Error reading object reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, id), - ex); - } - } - - private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) => (value & flag) == flag; - - private bool ShouldSetPropertyValue(JsonProperty property, JsonObjectContract? contract, object? value) - { - if (value == null && ResolvedNullValueHandling(contract, property) == NullValueHandling.Ignore) return false; - - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) - && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) - && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue())) - return false; - - if (!property.Writable) return false; - - return true; - } - - private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultCreator) - { - // some types like non-generic IEnumerable can be serialized but not deserialized - if (!contract.CanDeserialize) - throw JsonSerializationException.Create(reader, - "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); - - if (contract.OverrideCreator != null) - { - if (contract.HasParameterizedCreator) - { - createdFromNonDefaultCreator = true; - return contract.CreateTemporaryCollection(); - } - var list = contract.OverrideCreator(); - - if (contract.ShouldCreateWrapper) list = contract.CreateWrapper(list); - - createdFromNonDefaultCreator = false; - return (IList)list; - } - if (contract.IsReadOnlyOrFixedSize) - { - createdFromNonDefaultCreator = true; - var list = contract.CreateTemporaryCollection(); - - if (contract.ShouldCreateWrapper) list = contract.CreateWrapper(list); - - return list; - } - if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic - || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) - { - var list = contract.DefaultCreator(); - - if (contract.ShouldCreateWrapper) list = contract.CreateWrapper(list); - - createdFromNonDefaultCreator = false; - return (IList)list; - } - if (contract.HasParameterizedCreatorInternal) - { - createdFromNonDefaultCreator = true; - return contract.CreateTemporaryCollection(); - } - if (!contract.IsInstantiable) - throw JsonSerializationException.Create(reader, - "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - throw JsonSerializationException.Create(reader, - "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultCreator) - { - if (contract.OverrideCreator != null) - { - if (contract.HasParameterizedCreator) - { - createdFromNonDefaultCreator = true; - return contract.CreateTemporaryDictionary(); - } - createdFromNonDefaultCreator = false; - return (IDictionary)contract.OverrideCreator(); - } - if (contract.IsReadOnlyOrFixedSize) - { - createdFromNonDefaultCreator = true; - return contract.CreateTemporaryDictionary(); - } - if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic - || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) - { - var dictionary = contract.DefaultCreator(); - - if (contract.ShouldCreateWrapper) dictionary = contract.CreateWrapper(dictionary); - - createdFromNonDefaultCreator = false; - return (IDictionary)dictionary; - } - if (contract.HasParameterizedCreatorInternal) - { - createdFromNonDefaultCreator = true; - return contract.CreateTemporaryDictionary(); - } - if (!contract.IsInstantiable) - throw JsonSerializationException.Create(reader, - "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith( - CultureInfo.InvariantCulture, contract.UnderlyingType)); - - throw JsonSerializationException.Create(reader, - "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - private void OnDeserializing(JsonReader reader, JsonContract contract, object value) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); - - contract.InvokeOnDeserializing(value, Serializer._context); - } - - private void OnDeserialized(JsonReader reader, JsonContract contract, object value) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Finished deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); - - contract.InvokeOnDeserialized(value, Serializer._context); - } - - private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty? containerProperty, - string? id - ) - { - var underlyingDictionary = dictionary is IWrappedDictionary wrappedDictionary ? wrappedDictionary.UnderlyingDictionary : dictionary; - - if (id != null) AddReference(reader, id, underlyingDictionary); - - OnDeserializing(reader, contract, underlyingDictionary); - - var initialDepth = reader.Depth; - - if (contract.KeyContract == null) contract.KeyContract = GetContractSafe(contract.DictionaryKeyType); - - if (contract.ItemContract == null) contract.ItemContract = GetContractSafe(contract.DictionaryValueType); - - var dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); - var keyTypeCode = contract.KeyContract is JsonPrimitiveContract keyContract ? keyContract.TypeCode : PrimitiveTypeCode.Empty; - - var finished = false; - do - switch (reader.TokenType) - { - case JsonToken.PropertyName: - var keyValue = reader.Value!; - if (CheckPropertyName(reader, keyValue.ToString())) continue; - - try - { - try - { - // this is for correctly reading ISO and MS formatted dictionary keys - switch (keyTypeCode) - { - case PrimitiveTypeCode.DateTime: - case PrimitiveTypeCode.DateTimeNullable: - { - keyValue = DateTimeUtils.TryParseDateTime(keyValue.ToString(), reader.DateTimeZoneHandling, - reader.DateFormatString, reader.Culture, out var dt) - ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, - contract.DictionaryKeyType)!; - break; - } -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: - case PrimitiveTypeCode.DateTimeOffsetNullable: - { - keyValue = - DateTimeUtils.TryParseDateTimeOffset(keyValue.ToString(), reader.DateFormatString, reader.Culture, out DateTimeOffset dt) - ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)!; - break; - } -#endif - default: - keyValue = contract.KeyContract != null && contract.KeyContract.IsEnum - ? EnumUtils.ParseEnum(contract.KeyContract.NonNullableUnderlyingType, - (Serializer._contractResolver as DefaultContractResolver)?.NamingStrategy, keyValue.ToString(), false) - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, - contract.DictionaryKeyType)!; - break; - } - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object." - .FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex); - } - - if (!reader.ReadForType(contract.ItemContract, dictionaryValueConverter != null)) - throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); - - object? itemValue; - if (dictionaryValueConverter != null && dictionaryValueConverter.CanRead) - itemValue = DeserializeConvertable(dictionaryValueConverter, reader, contract.DictionaryValueType!, null); - else - itemValue = CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, - containerProperty, null); - - dictionary[keyValue] = itemValue; - } - catch (Exception ex) - { - if (IsErrorHandled(underlyingDictionary, contract, keyValue, reader as IJsonLineInfo, reader.Path, ex)) - HandleError(reader, true, initialDepth); - else - throw; - } - break; - case JsonToken.Comment: - break; - case JsonToken.EndObject: - finished = true; - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); - } - while (!finished && reader.Read()); - - if (!finished) ThrowUnexpectedEndException(reader, contract, underlyingDictionary, "Unexpected end when deserializing object."); - - OnDeserialized(reader, contract, underlyingDictionary); - return underlyingDictionary; - } - - private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, - string? id - ) - { - var rank = contract.UnderlyingType.GetArrayRank(); - - if (id != null) AddReference(reader, id, list); - - OnDeserializing(reader, contract, list); - - var collectionItemContract = GetContractSafe(contract.CollectionItemType); - var collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); - - int? previousErrorIndex = null; - var listStack = new Stack(); - listStack.Push(list); - var currentList = list; - - var finished = false; - do - { - var initialDepth = reader.Depth; - - if (listStack.Count == rank) - { - try - { - if (reader.ReadForType(collectionItemContract, collectionItemConverter != null)) - { - switch (reader.TokenType) - { - case JsonToken.EndArray: - listStack.Pop(); - currentList = listStack.Peek(); - previousErrorIndex = null; - break; - case JsonToken.Comment: - break; - default: - object? value; - - if (collectionItemConverter != null && collectionItemConverter.CanRead) - value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType!, null); - else - value = CreateValueInternal(reader, contract.CollectionItemType, collectionItemContract, null, contract, - containerProperty, null); - - currentList.Add(value); - break; - } - } - else - break; - } - catch (Exception ex) - { - var errorPosition = reader.GetPosition(initialDepth); - - if (IsErrorHandled(list, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex)) - { - HandleError(reader, true, initialDepth + 1); - - if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position) - { - // reader index has not moved since previous error handling - // break out of reading array to prevent infinite loop - throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); - } - previousErrorIndex = errorPosition.Position; - } - else - throw; - } - } - else - { - if (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.StartArray: - IList newList = new List(); - currentList.Add(newList); - listStack.Push(newList); - currentList = newList; - break; - case JsonToken.EndArray: - listStack.Pop(); - - if (listStack.Count > 0) - currentList = listStack.Peek(); - else - finished = true; - break; - case JsonToken.Comment: - break; - default: - throw JsonSerializationException.Create(reader, - "Unexpected token when deserializing multidimensional array: " + reader.TokenType); - } - } - else - break; - } - } while (!finished); - - if (!finished) ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array."); - - OnDeserialized(reader, contract, list); - return list; - } - - private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object? currentObject, string message) - { - try - { - throw JsonSerializationException.Create(reader, message); - } - catch (Exception ex) - { - if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex)) - HandleError(reader, false, 0); - else - throw; - } - } - - private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) - { -#pragma warning disable CS8600, CS8602, CS8603, CS8604 - var underlyingList = list is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : list; - - if (id != null) AddReference(reader, id, underlyingList); - - // can't populate an existing array - if (list.IsFixedSize) - { - reader.Skip(); - return underlyingList; - } - - OnDeserializing(reader, contract, underlyingList); - - var initialDepth = reader.Depth; - - if (contract.ItemContract == null) contract.ItemContract = GetContractSafe(contract.CollectionItemType); - - var collectionItemConverter = GetConverter(contract.ItemContract, null, contract, containerProperty); - - int? previousErrorIndex = null; - - var finished = false; - do - try - { - if (reader.ReadForType(contract.ItemContract, collectionItemConverter != null)) - { - switch (reader.TokenType) - { - case JsonToken.EndArray: - finished = true; - break; - case JsonToken.Comment: - break; - default: - object? value; - - if (collectionItemConverter != null && collectionItemConverter.CanRead) - value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null); - else - value = CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, - containerProperty, null); - - list.Add(value); - break; - } - } - else - break; - } - catch (Exception ex) - { - var errorPosition = reader.GetPosition(initialDepth); - - if (IsErrorHandled(underlyingList, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex)) - { - HandleError(reader, true, initialDepth + 1); - - if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position) - { - // reader index has not moved since previous error handling - // break out of reading array to prevent infinite loop - throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); - } - previousErrorIndex = errorPosition.Position; - } - else - throw; - } - while (!finished); - - if (!finished) ThrowUnexpectedEndException(reader, contract, underlyingList, "Unexpected end when deserializing array."); - - OnDeserialized(reader, contract, underlyingList); - return underlyingList; -#pragma warning restore CS8600, CS8602, CS8603, CS8604 - } - -#if HAVE_BINARY_SERIALIZATION - private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty? member, string? id) - { - Type objectType = contract.UnderlyingType; - - if (!JsonTypeReflector.FullyTrusted) - { - string message = - @"Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + - @"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; - message = message.FormatWith(CultureInfo.InvariantCulture, objectType); - - throw JsonSerializationException.Create(reader, message); - } - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - { - TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using ISerializable constructor.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); - } - -#pragma warning disable SYSLIB0050 - SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new JsonFormatterConverter(this, contract, member)); -#pragma warning restore SYSLIB0050 - - bool finished = false; - do - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - string memberName = reader.Value!.ToString(); - if (!reader.Read()) - { - throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - } - serializationInfo.AddValue(memberName, JToken.ReadFrom(reader)); - break; - case JsonToken.Comment: - break; - case JsonToken.EndObject: - finished = true; - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); - } - } while (!finished && reader.Read()); - - if (!finished) - { - ThrowUnexpectedEndException(reader, contract, serializationInfo, "Unexpected end when deserializing object."); - } - - if (!contract.IsInstantiable) - { - throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - if (contract.ISerializableCreator == null) - { - throw JsonSerializationException.Create(reader, "ISerializable type '{0}' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present.".FormatWith(CultureInfo.InvariantCulture, objectType)); - } - - object createdObject = contract.ISerializableCreator(serializationInfo, Serializer._context); - - if (id != null) - { - AddReference(reader, id, createdObject); - } - - // these are together because OnDeserializing takes an object but for an ISerializable the object is fully created in the constructor - OnDeserializing(reader, contract, createdObject); - OnDeserialized(reader, contract, createdObject); - - return createdObject; - } - - internal object? CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty? member) - { - JsonContract? itemContract = GetContractSafe(type); - JsonConverter? itemConverter = GetConverter(itemContract, null, contract, member); - - JsonReader tokenReader = token.CreateReader(); - tokenReader.ReadAndAssert(); // Move to first token - - object? result; - if (itemConverter != null && itemConverter.CanRead) - { - result = DeserializeConvertable(itemConverter, tokenReader, type, null); - } - else - { - result = CreateValueInternal(tokenReader, type, itemContract, null, contract, member, null); - } - - return result; - } -#endif - -#if HAVE_DYNAMIC - private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty? member, string? id) - { - IDynamicMetaObjectProvider newObject; - - if (!contract.IsInstantiable) - { - throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - if (contract.DefaultCreator != null && - (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) - { - newObject = (IDynamicMetaObjectProvider)contract.DefaultCreator(); - } - else - { - throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); - } - - if (id != null) - { - AddReference(reader, id, newObject); - } - - OnDeserializing(reader, contract, newObject); - - int initialDepth = reader.Depth; - - bool finished = false; - do - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - string memberName = reader.Value!.ToString(); - - try - { - if (!reader.Read()) - { - throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - } - - // first attempt to find a settable property, otherwise fall back to a dynamic set without type - JsonProperty? property = contract.Properties.GetClosestMatchProperty(memberName); - - if (property != null && property.Writable && !property.Ignored) - { - if (property.PropertyContract == null) - { - property.PropertyContract = GetContractSafe(property.PropertyType); - } - - JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, null, null); - - if (!SetPropertyValue(property, propertyConverter, null, member, reader, newObject)) - { - reader.Skip(); - } - } - else - { - Type t = (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType! : typeof(IDynamicMetaObjectProvider); - - JsonContract? dynamicMemberContract = GetContractSafe(t); - JsonConverter? dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member); - - object? value; - if (dynamicMemberConverter != null && dynamicMemberConverter.CanRead) - { - value = DeserializeConvertable(dynamicMemberConverter!, reader, t, null); - } - else - { - value = CreateValueInternal(reader, t, dynamicMemberContract, null, null, member, null); - } - - contract.TrySetMember(newObject, memberName, value); - } - } - catch (Exception ex) - { - if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, ex)) - { - HandleError(reader, true, initialDepth); - } - else - { - throw; - } - } - break; - case JsonToken.EndObject: - finished = true; - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); - } - } while (!finished && reader.Read()); - - if (!finished) - { - ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object."); - } - - OnDeserialized(reader, contract, newObject); - - return newObject; - } -#endif - - internal class CreatorPropertyContext - { - public readonly string Name; - - public CreatorPropertyContext(string name) => Name = name; - - public JsonProperty? ConstructorProperty; - public PropertyPresence? Presence; - public JsonProperty? Property; - public bool Used; - public object? Value; - } - - private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty? containerProperty, - ObjectConstructor creator, string? id - ) - { - ValidationUtils.ArgumentNotNull(creator, nameof(creator)); - - // only need to keep a track of properties' presence if they are required or a value should be defaulted if missing - var trackPresence = contract.HasRequiredOrDefaultValueProperties - || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate); - - var objectType = contract.UnderlyingType; - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - { - var parameters = string.Join(", ", contract.CreatorParameters.Select(p => p.PropertyName) -#if !HAVE_STRING_JOIN_WITH_ENUMERABLE - .ToArray() -#endif - ); - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, - parameters)), null); - } - - var propertyContexts = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, objectType); - if (trackPresence) - { - foreach (var property in contract.Properties) - { - if (!property.Ignored) - { - if (propertyContexts.All(p => p.Property != property)) - { - propertyContexts.Add(new CreatorPropertyContext(property.PropertyName!) - { - Property = property, Presence = PropertyPresence.None - }); - } - } - } - } - - var creatorParameterValues = new object?[contract.CreatorParameters.Count]; - - foreach (var context in propertyContexts) - { - // set presence of read values - if (trackPresence) - { - if (context.Property != null && context.Presence == null) - { - var v = context.Value; - PropertyPresence propertyPresence; - if (v == null) - propertyPresence = PropertyPresence.Null; - else if (v is string s) - { - propertyPresence = CoerceEmptyStringToNull(context.Property.PropertyType, context.Property.PropertyContract, s) - ? PropertyPresence.Null - : PropertyPresence.Value; - } - else - propertyPresence = PropertyPresence.Value; - - context.Presence = propertyPresence; - } - } - - var constructorProperty = context.ConstructorProperty; - if (constructorProperty == null && context.Property != null) - constructorProperty = - contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName!, context.Property.UnderlyingName!); - - if (constructorProperty != null && !constructorProperty.Ignored) - { - // handle giving default values to creator parameters - // this needs to happen before the call to creator - if (trackPresence) - { - if (context.Presence == PropertyPresence.None || context.Presence == PropertyPresence.Null) - { - if (constructorProperty.PropertyContract == null) - constructorProperty.PropertyContract = GetContractSafe(constructorProperty.PropertyType); - - if (HasFlag(constructorProperty.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), - DefaultValueHandling.Populate)) - { - context.Value = EnsureType( - reader, - constructorProperty.GetResolvedDefaultValue(), - CultureInfo.InvariantCulture, - constructorProperty.PropertyContract!, - constructorProperty.PropertyType); - } - } - } - - var i = contract.CreatorParameters.IndexOf(constructorProperty); - creatorParameterValues[i] = context.Value; - - context.Used = true; - } - } - - var createdObject = creator(creatorParameterValues); - - if (id != null) AddReference(reader, id, createdObject); - - OnDeserializing(reader, contract, createdObject); - - // go through unused values and set the newly created object's properties - foreach (var context in propertyContexts) - { - if (context.Used || - context.Property == null || - context.Property.Ignored || - context.Presence == PropertyPresence.None) - continue; - - var property = context.Property; - var value = context.Value; - - if (ShouldSetPropertyValue(property, contract, value)) - { - property.ValueProvider!.SetValue(createdObject, value); - context.Used = true; - } - else if (!property.Writable && value != null) - { - // handle readonly collection/dictionary properties - var propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType!); - - if (propertyContract.ContractType == JsonContractType.Array) - { - var propertyArrayContract = (JsonArrayContract)propertyContract; - - if (propertyArrayContract.CanDeserialize && !propertyArrayContract.IsReadOnlyOrFixedSize) - { - var createdObjectCollection = property.ValueProvider!.GetValue(createdObject); - if (createdObjectCollection != null) - { - propertyArrayContract = (JsonArrayContract)GetContract(createdObjectCollection.GetType()); - - var createdObjectCollectionWrapper = propertyArrayContract.ShouldCreateWrapper - ? propertyArrayContract.CreateWrapper(createdObjectCollection) - : (IList)createdObjectCollection; - - // Don't attempt to populate array/read-only list - if (!createdObjectCollectionWrapper.IsFixedSize) - { - var newValues = propertyArrayContract.ShouldCreateWrapper - ? propertyArrayContract.CreateWrapper(value) - : (IList)value; - - foreach (var newValue in newValues) createdObjectCollectionWrapper.Add(newValue); - } - } - } - } - else if (propertyContract.ContractType == JsonContractType.Dictionary) - { - var dictionaryContract = (JsonDictionaryContract)propertyContract; - - if (!dictionaryContract.IsReadOnlyOrFixedSize) - { - var createdObjectDictionary = property.ValueProvider!.GetValue(createdObject); - if (createdObjectDictionary != null) - { - var targetDictionary = dictionaryContract.ShouldCreateWrapper - ? dictionaryContract.CreateWrapper(createdObjectDictionary) - : (IDictionary)createdObjectDictionary; - var newValues = dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(value) : (IDictionary)value; - - // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations. - var e = newValues.GetEnumerator(); - try - { - while (e.MoveNext()) - { - var entry = e.Entry; - targetDictionary[entry.Key] = entry.Value; - } - } - finally - { - (e as IDisposable)?.Dispose(); - } - } - } - } - - context.Used = true; - } - } - - if (contract.ExtensionDataSetter != null) - { - foreach (var propertyValue in propertyContexts) - if (!propertyValue.Used && propertyValue.Presence != PropertyPresence.None) - contract.ExtensionDataSetter(createdObject, propertyValue.Name, propertyValue.Value); - } - - if (trackPresence) - { - foreach (var context in propertyContexts) - { - if (context.Property == null) continue; - - EndProcessProperty( - createdObject, - reader, - contract, - reader.Depth, - context.Property, - context.Presence.GetValueOrDefault(), - !context.Used); - } - } - - OnDeserialized(reader, contract, createdObject); - return createdObject; - } - - private object? DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object? existingValue) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), - null); - - var value = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer()); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Finished deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), - null); - - return value; - } - - private List ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty? containerProperty, - JsonReader reader, Type objectType - ) - { - var propertyValues = new List(); - var exit = false; - do - switch (reader.TokenType) - { - case JsonToken.PropertyName: - var memberName = reader.Value!.ToString(); - - var creatorPropertyContext = new CreatorPropertyContext(memberName) - { - ConstructorProperty = contract.CreatorParameters.GetClosestMatchProperty(memberName), - Property = contract.Properties.GetClosestMatchProperty(memberName) - }; - propertyValues.Add(creatorPropertyContext); - - var property = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; - if (property != null) - { - if (!property.Ignored) - { - if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); - - var propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, containerProperty); - - if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) - throw JsonSerializationException.Create(reader, - "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - - if (propertyConverter != null && propertyConverter.CanRead) - creatorPropertyContext.Value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, null); - else - creatorPropertyContext.Value = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, - property, contract, containerProperty, null); - - continue; - } - } - else - { - if (!reader.Read()) - throw JsonSerializationException.Create(reader, - "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, memberName, - contract.UnderlyingType)), null); - - if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) - throw JsonSerializationException.Create(reader, - "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, - objectType.Name)); - } - - if (contract.ExtensionDataSetter != null) - creatorPropertyContext.Value = ReadExtensionDataValue(contract, containerProperty, reader); - else - reader.Skip(); - break; - case JsonToken.Comment: - break; - case JsonToken.EndObject: - exit = true; - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); - } - while (!exit && reader.Read()); - - if (!exit) ThrowUnexpectedEndException(reader, contract, null, "Unexpected end when deserializing object."); - - return propertyValues; - } - - public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty? containerMember, - JsonProperty? containerProperty, string? id, out bool createdFromNonDefaultCreator - ) - { - object? newObject = null; - - if (objectContract.OverrideCreator != null) - { - if (objectContract.CreatorParameters.Count > 0) - { - createdFromNonDefaultCreator = true; - return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id); - } - - newObject = objectContract.OverrideCreator(CollectionUtils.ArrayEmpty()); - } - else if (objectContract.DefaultCreator != null && - (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor - || objectContract.ParameterizedCreator == null)) - { - // use the default constructor if it is... - // public - // non-public and the user has change constructor handling settings - // non-public and there is no other creator - newObject = objectContract.DefaultCreator(); - } - else if (objectContract.ParameterizedCreator != null) - { - createdFromNonDefaultCreator = true; - return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParameterizedCreator, id); - } - - if (newObject == null) - { - if (!objectContract.IsInstantiable) - throw JsonSerializationException.Create(reader, - "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith( - CultureInfo.InvariantCulture, objectContract.UnderlyingType)); - - throw JsonSerializationException.Create(reader, - "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute." - .FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); - } - - createdFromNonDefaultCreator = false; - return newObject; - } - - private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty? member, string? id) - { - OnDeserializing(reader, contract, newObject); - - // only need to keep a track of properties' presence if they are required or a value should be defaulted if missing - var propertiesPresence = contract.HasRequiredOrDefaultValueProperties - || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate) - ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None) - : null; - - if (id != null) AddReference(reader, id, newObject); - - var initialDepth = reader.Depth; - - var finished = false; - do - switch (reader.TokenType) - { - case JsonToken.PropertyName: - { - var propertyName = reader.Value!.ToString(); - - if (CheckPropertyName(reader, propertyName)) continue; - - try - { - // attempt exact case match first - // then try match ignoring case - var property = contract.Properties.GetClosestMatchProperty(propertyName); - - if (property == null) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, - "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, propertyName, - contract.UnderlyingType)), null); - - if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) - throw JsonSerializationException.Create(reader, - "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, propertyName, - contract.UnderlyingType.Name)); - - if (!reader.Read()) break; - - SetExtensionData(contract, member, reader, propertyName, newObject); - continue; - } - - if (property.Ignored || !ShouldDeserialize(reader, property, newObject)) - { - if (!reader.Read()) break; - - SetPropertyPresence(reader, property, propertiesPresence); - SetExtensionData(contract, member, reader, propertyName, newObject); - } - else - { - if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); - - var propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, member); - - if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) - throw JsonSerializationException.Create(reader, - "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, propertyName)); - - SetPropertyPresence(reader, property, propertiesPresence); - - // set extension data if property is ignored or readonly - if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject)) - SetExtensionData(contract, member, reader, propertyName, newObject); - } - } - catch (Exception ex) - { - if (IsErrorHandled(newObject, contract, propertyName, reader as IJsonLineInfo, reader.Path, ex)) - HandleError(reader, true, initialDepth); - else - throw; - } - break; - } - case JsonToken.EndObject: - finished = true; - break; - case JsonToken.Comment: - // ignore - break; - default: - throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); - } - while (!finished && reader.Read()); - - if (!finished) ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object."); - - if (propertiesPresence != null) - { - foreach (var propertyPresence in propertiesPresence) - { - var property = propertyPresence.Key; - var presence = propertyPresence.Value; - - EndProcessProperty(newObject, reader, contract, initialDepth, property, presence, true); - } - } - - OnDeserialized(reader, contract, newObject); - return newObject; - } - - private bool ShouldDeserialize(JsonReader reader, JsonProperty property, object target) - { - if (property.ShouldDeserialize == null) return true; - - var shouldDeserialize = property.ShouldDeserialize(target); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, reader.Path, - "ShouldDeserialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, - property.DeclaringType, shouldDeserialize)), null); - - return shouldDeserialize; - } - - private bool CheckPropertyName(JsonReader reader, string memberName) - { - if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) - { - switch (memberName) - { - case JsonTypeReflector.IdPropertyName: - case JsonTypeReflector.RefPropertyName: - case JsonTypeReflector.TypePropertyName: - case JsonTypeReflector.ArrayValuesPropertyName: - reader.Skip(); - return true; - } - } - return false; - } - - private void SetExtensionData(JsonObjectContract contract, JsonProperty? member, JsonReader reader, string memberName, object o) - { - if (contract.ExtensionDataSetter != null) - { - try - { - var value = ReadExtensionDataValue(contract, member, reader); - - contract.ExtensionDataSetter(o, memberName, value); - } - catch (Exception ex) - { - throw JsonSerializationException.Create(reader, - "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), - ex); - } - } - else - reader.Skip(); - } - - private object? ReadExtensionDataValue(JsonObjectContract contract, JsonProperty? member, JsonReader reader) - { - object? value; - if (contract.ExtensionDataIsJToken) - value = JToken.ReadFrom(reader); - else - value = CreateValueInternal(reader, null, null, null, contract, member, null); - return value; - } - - private void EndProcessProperty(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, JsonProperty property, - PropertyPresence presence, bool setDefaultValue - ) - { - if (presence == PropertyPresence.None || presence == PropertyPresence.Null) - { - try - { - var resolvedRequired = property.Ignored ? Required.Default : property._required ?? contract.ItemRequired ?? Required.Default; - - switch (presence) - { - case PropertyPresence.None: - if (resolvedRequired == Required.AllowNull || resolvedRequired == Required.Always) - throw JsonSerializationException.Create(reader, - "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); - - if (setDefaultValue && !property.Ignored) - { - if (property.PropertyContract == null) property.PropertyContract = GetContractSafe(property.PropertyType); - - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), - DefaultValueHandling.Populate) && property.Writable) - property.ValueProvider!.SetValue(newObject, - EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, - property.PropertyContract!, property.PropertyType)); - } - break; - case PropertyPresence.Null: - if (resolvedRequired == Required.Always) - throw JsonSerializationException.Create(reader, - "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, - property.PropertyName)); - - if (resolvedRequired == Required.DisallowNull) - throw JsonSerializationException.Create(reader, - "Required property '{0}' expects a non-null value.".FormatWith(CultureInfo.InvariantCulture, - property.PropertyName)); - - break; - } - } - catch (Exception ex) - { - if (IsErrorHandled(newObject, contract, property.PropertyName, reader as IJsonLineInfo, reader.Path, ex)) - HandleError(reader, true, initialDepth); - else - throw; - } - } - } - - private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary? requiredProperties) - { - if (property != null && requiredProperties != null) - { - PropertyPresence propertyPresence; - switch (reader.TokenType) - { - case JsonToken.String: - propertyPresence = CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value!) - ? PropertyPresence.Null - : PropertyPresence.Value; - break; - case JsonToken.Null: - case JsonToken.Undefined: - propertyPresence = PropertyPresence.Null; - break; - default: - propertyPresence = PropertyPresence.Value; - break; - } - - requiredProperties[property] = propertyPresence; - } - } - - private void HandleError(JsonReader reader, bool readPastError, int initialDepth) - { - ClearErrorContext(); - - if (readPastError) - { - reader.Skip(); - - while (reader.Depth > initialDepth) - if (!reader.Read()) - break; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs deleted file mode 100644 index 2bc1540b8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ /dev/null @@ -1,1100 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System.Dynamic; -#endif -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Runtime.Serialization; -using System.Security; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class JsonSerializerInternalWriter : JsonSerializerInternalBase - { - private Type? _rootType; - private int _rootLevel; - private readonly List _serializeStack = new(); - - public JsonSerializerInternalWriter(JsonSerializer serializer) - : base(serializer) { } - - public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) - { - if (jsonWriter == null) throw new ArgumentNullException(nameof(jsonWriter)); - - _rootType = objectType; - _rootLevel = _serializeStack.Count + 1; - - var contract = GetContractSafe(value); - - try - { - if (ShouldWriteReference(value, null, contract, null, null)) - WriteReference(jsonWriter, value!); - else - SerializeValue(jsonWriter, value, contract, null, null, null); - } - catch (Exception ex) - { - if (IsErrorHandled(null, contract, null, null, jsonWriter.Path, ex)) - HandleError(jsonWriter, 0); - else - { - // clear context in case serializer is being used inside a converter - // if the converter wraps the error then not clearing the context will cause this error: - // "Current error context error is different to requested error." - ClearErrorContext(); - throw; - } - } - finally - { - // clear root contract to ensure that if level was > 1 then it won't - // accidentally be used for non root values - _rootType = null; - } - } - - private JsonSerializerProxy GetInternalSerializer() - { - if (InternalSerializer == null) InternalSerializer = new JsonSerializerProxy(this); - - return InternalSerializer; - } - - private JsonContract? GetContractSafe(object? value) - { - if (value == null) return null; - - return GetContract(value); - } - - private JsonContract GetContract(object value) => Serializer._contractResolver.ResolveContract(value.GetType()); - - private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerProperty - ) - { - if (contract.TypeCode == PrimitiveTypeCode.Bytes) - { - // if type name handling is enabled then wrap the base64 byte string in an object with the type name - var includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty); - if (includeTypeDetails) - { - writer.WriteStartObject(); - WriteTypeProperty(writer, contract.CreatedType); - writer.WritePropertyName(JsonTypeReflector.ValuePropertyName, false); - - JsonWriter.WriteValue(writer, contract.TypeCode, value); - - writer.WriteEndObject(); - return; - } - } - - JsonWriter.WriteValue(writer, contract.TypeCode, value); - } - - private void SerializeValue(JsonWriter writer, object? value, JsonContract? valueContract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerProperty - ) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - MiscellaneousUtils.Assert(valueContract != null); - - var converter = - member?.Converter ?? - containerProperty?.ItemConverter ?? - containerContract?.ItemConverter ?? - valueContract.Converter ?? - Serializer.GetMatchingConverter(valueContract.UnderlyingType) ?? - valueContract.InternalConverter; - - if (converter != null && converter.CanWrite) - { - SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty); - return; - } - - switch (valueContract.ContractType) - { - case JsonContractType.Object: - SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty); - break; - case JsonContractType.Array: - var arrayContract = (JsonArrayContract)valueContract; - if (!arrayContract.IsMultidimensionalArray) - SerializeList(writer, (IEnumerable)value, arrayContract, member, containerContract, containerProperty); - else - SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty); - break; - case JsonContractType.Primitive: - SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty); - break; - case JsonContractType.String: - SerializeString(writer, value, (JsonStringContract)valueContract); - break; - case JsonContractType.Dictionary: - var dictionaryContract = (JsonDictionaryContract)valueContract; - SerializeDictionary(writer, value is IDictionary dictionary ? dictionary : dictionaryContract.CreateWrapper(value), - dictionaryContract, member, containerContract, containerProperty); - break; -#if HAVE_DYNAMIC - case JsonContractType.Dynamic: - SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); - break; -#endif -#if HAVE_BINARY_SERIALIZATION - case JsonContractType.Serializable: - SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); - break; -#endif - case JsonContractType.Linq: - ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray()); - break; - } - } - - private bool? ResolveIsReference(JsonContract contract, JsonProperty? property, JsonContainerContract? collectionContract, - JsonProperty? containerProperty - ) - { - bool? isReference = null; - - // value could be coming from a dictionary or array and not have a property - if (property != null) isReference = property.IsReference; - - if (isReference == null && containerProperty != null) isReference = containerProperty.ItemIsReference; - - if (isReference == null && collectionContract != null) isReference = collectionContract.ItemIsReference; - - if (isReference == null) isReference = contract.IsReference; - - return isReference; - } - - private bool ShouldWriteReference(object? value, JsonProperty? property, JsonContract? valueContract, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - if (value == null) return false; - - MiscellaneousUtils.Assert(valueContract != null); - - if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String) return false; - - var isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty); - - if (isReference == null) - { - if (valueContract.ContractType == JsonContractType.Array) - isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays); - else - isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects); - } - - if (!isReference.GetValueOrDefault()) return false; - - return Serializer.GetReferenceResolver().IsReferenced(this, value); - } - - private bool ShouldWriteProperty(object? memberValue, JsonObjectContract? containerContract, JsonProperty property) - { - if (memberValue == null && ResolvedNullValueHandling(containerContract, property) == NullValueHandling.Ignore) return false; - - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) - && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue())) - return false; - - return true; - } - - private bool CheckForCircularReference(JsonWriter writer, object? value, JsonProperty? property, JsonContract? contract, - JsonContainerContract? containerContract, JsonProperty? containerProperty - ) - { - if (value == null) return true; - - MiscellaneousUtils.Assert(contract != null); - - if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) return true; - - ReferenceLoopHandling? referenceLoopHandling = null; - - if (property != null) referenceLoopHandling = property.ReferenceLoopHandling; - - if (referenceLoopHandling == null && containerProperty != null) referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; - - if (referenceLoopHandling == null && containerContract != null) referenceLoopHandling = containerContract.ItemReferenceLoopHandling; - - var exists = Serializer._equalityComparer != null - ? _serializeStack.Contains(value, Serializer._equalityComparer) - : _serializeStack.Contains(value); - - if (exists) - { - var message = "Self referencing loop detected"; - if (property != null) message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); - message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); - - switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling)) - { - case ReferenceLoopHandling.Error: - throw JsonSerializationException.Create(null, writer.ContainerPath, message, null); - case ReferenceLoopHandling.Ignore: - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null); - - return false; - case ReferenceLoopHandling.Serialize: - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null); - - return true; - } - } - - return true; - } - - private void WriteReference(JsonWriter writer, object value) - { - var reference = GetReference(writer, value); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(null, writer.Path, - "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null); - - writer.WriteStartObject(); - writer.WritePropertyName(JsonTypeReflector.RefPropertyName, false); - writer.WriteValue(reference); - writer.WriteEndObject(); - } - - private string GetReference(JsonWriter writer, object value) - { - try - { - var reference = Serializer.GetReferenceResolver().GetReference(this, value); - - return reference; - } - catch (Exception ex) - { - throw JsonSerializationException.Create(null, writer.ContainerPath, - "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex); - } - } - - internal static bool TryConvertToString(object value, Type type, [NotNullWhen(true)] out string? s) - { -#if HAVE_TYPE_DESCRIPTOR - if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter converter)) - { - s = converter.ConvertToInvariantString(value); - return true; - } -#endif - -#if (DOTNET || PORTABLE) - if (value is Guid || value is Uri || value is TimeSpan) - { - s = value.ToString(); - return true; - } -#endif - - if (value is Type t) - { - s = t.AssemblyQualifiedName; - return true; - } - - s = null; - return false; - } - - private void SerializeString(JsonWriter writer, object value, JsonStringContract contract) - { - OnSerializing(writer, contract, value); - - TryConvertToString(value, contract.UnderlyingType, out var s); - writer.WriteValue(s); - - OnSerialized(writer, contract, value); - } - - private void OnSerializing(JsonWriter writer, JsonContract contract, object value) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(null, writer.Path, - "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); - - contract.InvokeOnSerializing(value, Serializer._context); - } - - private void OnSerialized(JsonWriter writer, JsonContract contract, object value) - { - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(null, writer.Path, - "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); - - contract.InvokeOnSerialized(value, Serializer._context); - } - - private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty? member, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - OnSerializing(writer, contract, value); - - _serializeStack.Add(value); - - WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); - - var initialDepth = writer.Top; - - for (var index = 0; index < contract.Properties.Count; index++) - { - var property = contract.Properties[index]; - try - { - if (!CalculatePropertyValues(writer, value, contract, member, property, out var memberContract, out var memberValue)) continue; - - property.WritePropertyName(writer); - SerializeValue(writer, memberValue, memberContract, property, contract, member); - } - catch (Exception ex) - { - if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex)) - HandleError(writer, initialDepth); - else - throw; - } - } - - var extensionData = contract.ExtensionDataGetter?.Invoke(value); - if (extensionData != null) - { - foreach (var e in extensionData) - { - var keyContract = GetContract(e.Key); - var valueContract = GetContractSafe(e.Value); - - var propertyName = GetPropertyName(writer, e.Key, keyContract, out _); - - propertyName = contract.ExtensionDataNameResolver != null - ? contract.ExtensionDataNameResolver(propertyName) - : propertyName; - - if (ShouldWriteReference(e.Value, null, valueContract, contract, member)) - { - writer.WritePropertyName(propertyName); - WriteReference(writer, e.Value!); - } - else - { - if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member)) continue; - - writer.WritePropertyName(propertyName); - - SerializeValue(writer, e.Value, valueContract, null, contract, member); - } - } - } - - writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - - OnSerialized(writer, contract, value); - } - - private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, - JsonProperty property, [NotNullWhen(true)] out JsonContract? memberContract, out object? memberValue - ) - { - if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) - { - if (property.PropertyContract == null) - property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType!); - - memberValue = property.ValueProvider!.GetValue(value); - memberContract = property.PropertyContract.IsSealed ? property.PropertyContract : GetContractSafe(memberValue); - - if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) - { - if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) - { - property.WritePropertyName(writer); - WriteReference(writer, memberValue!); - return false; - } - - if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) return false; - - if (memberValue == null) - { - var objectContract = contract as JsonObjectContract; - var resolvedRequired = property._required ?? objectContract?.ItemRequired ?? Required.Default; - if (resolvedRequired == Required.Always) - throw JsonSerializationException.Create(null, writer.ContainerPath, - "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, - property.PropertyName), null); - - if (resolvedRequired == Required.DisallowNull) - throw JsonSerializationException.Create(null, writer.ContainerPath, - "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith( - CultureInfo.InvariantCulture, property.PropertyName), null); - } - -#pragma warning disable CS8762 // Parameter must have a non-null value when exiting in some condition. - return true; -#pragma warning restore CS8762 // Parameter must have a non-null value when exiting in some condition. - } - } - - memberContract = null; - memberValue = null; - return false; - } - - private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty? member, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - writer.WriteStartObject(); - - var isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) - ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects); - // don't make readonly fields that aren't creator parameters the referenced value because they can't be deserialized to - if (isReference && (member == null || member.Writable || HasCreatorParameter(collectionContract, member))) - WriteReferenceIdProperty(writer, contract.UnderlyingType, value); - if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) - WriteTypeProperty(writer, contract.UnderlyingType); - } - - private bool HasCreatorParameter(JsonContainerContract? contract, JsonProperty property) - { - if (!(contract is JsonObjectContract objectContract)) return false; - - return objectContract.CreatorParameters.Contains(property.PropertyName!); - } - - private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value) - { - var reference = GetReference(writer, value); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, - "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null); - - writer.WritePropertyName(JsonTypeReflector.IdPropertyName, false); - writer.WriteValue(reference); - } - - private void WriteTypeProperty(JsonWriter writer, Type type) - { - var typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormatHandling, Serializer._serializationBinder); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, - "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null); - - writer.WritePropertyName(JsonTypeReflector.TypePropertyName, false); - writer.WriteValue(typeName); - } - - private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) => (value & flag) == flag; - - private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag) => (value & flag) == flag; - - private bool HasFlag(TypeNameHandling value, TypeNameHandling flag) => (value & flag) == flag; - - private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) - WriteReference(writer, value); - else - { - if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty)) return; - - _serializeStack.Add(value); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(null, writer.Path, - "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), - converter.GetType())), null); - - converter.WriteJson(writer, value, GetInternalSerializer()); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) - TraceWriter.Trace(TraceLevel.Info, - JsonPosition.FormatMessage(null, writer.Path, - "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), - converter.GetType())), null); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - } - } - - private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty? member, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - var underlyingList = values is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : values; - - OnSerializing(writer, contract, underlyingList); - - _serializeStack.Add(underlyingList); - - var hasWrittenMetadataObject = WriteStartArray(writer, underlyingList, contract, member, collectionContract, containerProperty); - - writer.WriteStartArray(); - - var initialDepth = writer.Top; - - var index = 0; - // note that an error in the IEnumerable won't be caught - foreach (var value in values) - { - try - { - var valueContract = contract.FinalItemContract ?? GetContractSafe(value); - - if (ShouldWriteReference(value, null, valueContract, contract, member)) - WriteReference(writer, value); - else - { - if (CheckForCircularReference(writer, value, null, valueContract, contract, member)) - SerializeValue(writer, value, valueContract, null, contract, member); - } - } - catch (Exception ex) - { - if (IsErrorHandled(underlyingList, contract, index, null, writer.ContainerPath, ex)) - HandleError(writer, initialDepth); - else - throw; - } - finally - { - index++; - } - } - - writer.WriteEndArray(); - - if (hasWrittenMetadataObject) writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - - OnSerialized(writer, contract, underlyingList); - } - - private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { - OnSerializing(writer, contract, values); - - _serializeStack.Add(values); - - var hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); - - SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty()); - - if (hasWrittenMetadataObject) writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - - OnSerialized(writer, contract, values); - } - - private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, - int initialDepth, int[] indices - ) - { - var dimension = indices.Length; - var newIndices = new int[dimension + 1]; - for (var i = 0; i < dimension; i++) newIndices[i] = indices[i]; - - writer.WriteStartArray(); - - for (var i = values.GetLowerBound(dimension); i <= values.GetUpperBound(dimension); i++) - { - newIndices[dimension] = i; - var isTopLevel = newIndices.Length == values.Rank; - - if (isTopLevel) - { - var value = values.GetValue(newIndices); - - try - { - var valueContract = contract.FinalItemContract ?? GetContractSafe(value); - - if (ShouldWriteReference(value, null, valueContract, contract, member)) - WriteReference(writer, value); - else - { - if (CheckForCircularReference(writer, value, null, valueContract, contract, member)) - SerializeValue(writer, value, valueContract, null, contract, member); - } - } - catch (Exception ex) - { - if (IsErrorHandled(values, contract, i, null, writer.ContainerPath, ex)) - HandleError(writer, initialDepth + 1); - else - throw; - } - } - else - SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices); - } - - writer.WriteEndArray(); - } - - private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerProperty - ) - { - var isReference = ResolveIsReference(contract, member, containerContract, containerProperty) - ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays); - // don't make readonly fields that aren't creator parameters the referenced value because they can't be deserialized to - isReference = isReference && (member == null || member.Writable || HasCreatorParameter(containerContract, member)); - - var includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); - var writeMetadataObject = isReference || includeTypeDetails; - - if (writeMetadataObject) - { - writer.WriteStartObject(); - - if (isReference) WriteReferenceIdProperty(writer, contract.UnderlyingType, values); - if (includeTypeDetails) WriteTypeProperty(writer, values.GetType()); - writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName, false); - } - - if (contract.ItemContract == null) - contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); - - return writeMetadataObject; - } - -#if HAVE_BINARY_SERIALIZATION -#if HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE - [SecuritySafeCritical] -#endif - private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) - { - if (!JsonTypeReflector.FullyTrusted) - { - string message = - @"Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + - @"To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; - message = message.FormatWith(CultureInfo.InvariantCulture, value.GetType()); - - throw JsonSerializationException.Create(null, writer.ContainerPath, message, null); - } - - OnSerializing(writer, contract, value); - _serializeStack.Add(value); - - WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); - -#pragma warning disable SYSLIB0050 - SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); - value.GetObjectData(serializationInfo, Serializer._context); -#pragma warning restore SYSLIB0050 - - foreach (SerializationEntry serializationEntry in serializationInfo) - { - JsonContract? valueContract = GetContractSafe(serializationEntry.Value); - - if (ShouldWriteReference(serializationEntry.Value, null, valueContract, contract, member)) - { - writer.WritePropertyName(serializationEntry.Name); - WriteReference(writer, serializationEntry.Value); - } - else if (CheckForCircularReference(writer, serializationEntry.Value, null, valueContract, contract, member)) - { - writer.WritePropertyName(serializationEntry.Name); - SerializeValue(writer, serializationEntry.Value, valueContract, null, contract, member); - } - } - - writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - OnSerialized(writer, contract, value); - } -#endif - -#if HAVE_DYNAMIC - private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) - { - OnSerializing(writer, contract, value); - _serializeStack.Add(value); - - WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); - - int initialDepth = writer.Top; - - for (int index = 0; index < contract.Properties.Count; index++) - { - JsonProperty property = contract.Properties[index]; - - // only write non-dynamic properties that have an explicit attribute - if (property.HasMemberAttribute) - { - try - { - if (!CalculatePropertyValues(writer, value, contract, member, property, out JsonContract? memberContract, out object? memberValue)) - { - continue; - } - - property.WritePropertyName(writer); - SerializeValue(writer, memberValue, memberContract, property, contract, member); - } - catch (Exception ex) - { - if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex)) - { - HandleError(writer, initialDepth); - } - else - { - throw; - } - } - } - } - - foreach (string memberName in value.GetDynamicMemberNames()) - { - if (contract.TryGetMember(value, memberName, out object? memberValue)) - { - try - { - JsonContract? valueContract = GetContractSafe(memberValue); - - if (!ShouldWriteDynamicProperty(memberValue)) - { - continue; - } - - if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member)) - { - string resolvedPropertyName = (contract.PropertyNameResolver != null) - ? contract.PropertyNameResolver(memberName) - : memberName; - - writer.WritePropertyName(resolvedPropertyName); - SerializeValue(writer, memberValue, valueContract, null, contract, member); - } - } - catch (Exception ex) - { - if (IsErrorHandled(value, contract, memberName, null, writer.ContainerPath, ex)) - { - HandleError(writer, initialDepth); - } - else - { - throw; - } - } - } - } - - writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - OnSerialized(writer, contract, value); - } -#endif - - private bool ShouldWriteDynamicProperty(object? memberValue) - { - if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null) return false; - - if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) && - (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType())))) - return false; - - return true; - } - - private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty? member, - JsonContainerContract? containerContract, JsonProperty? containerProperty - ) - { - var resolvedTypeNameHandling = - member?.TypeNameHandling - ?? containerProperty?.ItemTypeNameHandling - ?? containerContract?.ItemTypeNameHandling - ?? Serializer._typeNameHandling; - - if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag)) return true; - - // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default) - if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto)) - { - if (member != null) - { - if (contract.NonNullableUnderlyingType != member.PropertyContract!.CreatedType) return true; - } - else if (containerContract != null) - { - if (containerContract.ItemContract == null - || contract.NonNullableUnderlyingType != containerContract.ItemContract.CreatedType) return true; - } - else if (_rootType != null && _serializeStack.Count == _rootLevel) - { - var rootContract = Serializer._contractResolver.ResolveContract(_rootType); - - if (contract.NonNullableUnderlyingType != rootContract.CreatedType) return true; - } - } - - return false; - } - - private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty? member, - JsonContainerContract? collectionContract, JsonProperty? containerProperty - ) - { -#pragma warning disable CS8600, CS8602, CS8604 - var underlyingDictionary = values is IWrappedDictionary wrappedDictionary ? wrappedDictionary.UnderlyingDictionary : values; - - OnSerializing(writer, contract, underlyingDictionary); - _serializeStack.Add(underlyingDictionary); - - WriteObjectStart(writer, underlyingDictionary, contract, member, collectionContract, containerProperty); - - if (contract.ItemContract == null) - contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); - - if (contract.KeyContract == null) - contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object)); - - var initialDepth = writer.Top; - - // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations. - var e = values.GetEnumerator(); - try - { - while (e.MoveNext()) - { - var entry = e.Entry; - - var propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out var escape); - - propertyName = contract.DictionaryKeyResolver != null - ? contract.DictionaryKeyResolver(propertyName) - : propertyName; - - try - { - var value = entry.Value; - var valueContract = contract.FinalItemContract ?? GetContractSafe(value); - - if (ShouldWriteReference(value, null, valueContract, contract, member)) - { - writer.WritePropertyName(propertyName, escape); - WriteReference(writer, value); - } - else - { - if (!CheckForCircularReference(writer, value, null, valueContract, contract, member)) continue; - - writer.WritePropertyName(propertyName, escape); - - SerializeValue(writer, value, valueContract, null, contract, member); - } - } - catch (Exception ex) - { - if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex)) - HandleError(writer, initialDepth); - else - throw; - } - } - } - finally - { - (e as IDisposable)?.Dispose(); - } - - writer.WriteEndObject(); - - _serializeStack.RemoveAt(_serializeStack.Count - 1); - - OnSerialized(writer, contract, underlyingDictionary); -#pragma warning restore CS8600, CS8602, CS8604 - } - - private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape) - { - if (contract.ContractType == JsonContractType.Primitive) - { - var primitiveContract = (JsonPrimitiveContract)contract; - switch (primitiveContract.TypeCode) - { - case PrimitiveTypeCode.DateTime: - case PrimitiveTypeCode.DateTimeNullable: - { - var dt = DateTimeUtils.EnsureDateTime((DateTime)name, writer.DateTimeZoneHandling); - - escape = false; - var sw = new StringWriter(CultureInfo.InvariantCulture); - DateTimeUtils.WriteDateTimeString(sw, dt, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); - return sw.ToString(); - } -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: - case PrimitiveTypeCode.DateTimeOffsetNullable: - { - escape = false; - StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); - DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); - return sw.ToString(); - } -#endif - case PrimitiveTypeCode.Double: - case PrimitiveTypeCode.DoubleNullable: - { - var d = (double)name; - - escape = false; - return d.ToString("R", CultureInfo.InvariantCulture); - } - case PrimitiveTypeCode.Single: - case PrimitiveTypeCode.SingleNullable: - { - var f = (float)name; - - escape = false; - return f.ToString("R", CultureInfo.InvariantCulture); - } - default: - { - escape = true; - - if (primitiveContract.IsEnum - && EnumUtils.TryToString(primitiveContract.NonNullableUnderlyingType, name, null, out var enumName)) return enumName; - - return Convert.ToString(name, CultureInfo.InvariantCulture); - } - } - } - if (TryConvertToString(name, name.GetType(), out var propertyName)) - { - escape = true; - return propertyName; - } - escape = true; - return name.ToString(); - } - - private void HandleError(JsonWriter writer, int initialDepth) - { - ClearErrorContext(); - - if (writer.WriteState == WriteState.Property) writer.WriteNull(); - - while (writer.Top > initialDepth) writer.WriteEnd(); - } - - private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target) - { - if (property.ShouldSerialize == null) return true; - - var shouldSerialize = property.ShouldSerialize(target); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, - "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, - property.DeclaringType, shouldSerialize)), null); - - return shouldSerialize; - } - - private bool IsSpecified(JsonWriter writer, JsonProperty property, object target) - { - if (property.GetIsSpecified == null) return true; - - var isSpecified = property.GetIsSpecified(target); - - if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) - TraceWriter.Trace(TraceLevel.Verbose, - JsonPosition.FormatMessage(null, writer.Path, - "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, - property.DeclaringType, isSpecified)), null); - - return isSpecified; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs deleted file mode 100644 index fb8ff5652..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ /dev/null @@ -1,276 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Globalization; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class JsonSerializerProxy : JsonSerializer - { - private readonly JsonSerializer _serializer; - private readonly JsonSerializerInternalReader? _serializerReader; - private readonly JsonSerializerInternalWriter? _serializerWriter; - - public JsonSerializerProxy(JsonSerializerInternalReader serializerReader) - { - ValidationUtils.ArgumentNotNull(serializerReader, nameof(serializerReader)); - - _serializerReader = serializerReader; - _serializer = serializerReader.Serializer; - } - - public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter) - { - ValidationUtils.ArgumentNotNull(serializerWriter, nameof(serializerWriter)); - - _serializerWriter = serializerWriter; - _serializer = serializerWriter.Serializer; - } - - [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] - public override SerializationBinder Binder - { - get => _serializer.Binder; - set => _serializer.Binder = value; - } - - public override bool CheckAdditionalContent - { - get => _serializer.CheckAdditionalContent; - set => _serializer.CheckAdditionalContent = value; - } - - public override ConstructorHandling ConstructorHandling - { - get => _serializer.ConstructorHandling; - set => _serializer.ConstructorHandling = value; - } - - public override StreamingContext Context - { - get => _serializer.Context; - set => _serializer.Context = value; - } - - public override IContractResolver ContractResolver - { - get => _serializer.ContractResolver; - set => _serializer.ContractResolver = value; - } - - public override JsonConverterCollection Converters => _serializer.Converters; - - public override CultureInfo Culture - { - get => _serializer.Culture; - set => _serializer.Culture = value; - } - - public override DateFormatHandling DateFormatHandling - { - get => _serializer.DateFormatHandling; - set => _serializer.DateFormatHandling = value; - } - - public override string DateFormatString - { - get => _serializer.DateFormatString; - set => _serializer.DateFormatString = value; - } - - public override DateParseHandling DateParseHandling - { - get => _serializer.DateParseHandling; - set => _serializer.DateParseHandling = value; - } - - public override DateTimeZoneHandling DateTimeZoneHandling - { - get => _serializer.DateTimeZoneHandling; - set => _serializer.DateTimeZoneHandling = value; - } - - public override DefaultValueHandling DefaultValueHandling - { - get => _serializer.DefaultValueHandling; - set => _serializer.DefaultValueHandling = value; - } - - public override IEqualityComparer? EqualityComparer - { - get => _serializer.EqualityComparer; - set => _serializer.EqualityComparer = value; - } - - public override FloatFormatHandling FloatFormatHandling - { - get => _serializer.FloatFormatHandling; - set => _serializer.FloatFormatHandling = value; - } - - public override FloatParseHandling FloatParseHandling - { - get => _serializer.FloatParseHandling; - set => _serializer.FloatParseHandling = value; - } - - public override Formatting Formatting - { - get => _serializer.Formatting; - set => _serializer.Formatting = value; - } - - public override int? MaxDepth - { - get => _serializer.MaxDepth; - set => _serializer.MaxDepth = value; - } - - public override MetadataPropertyHandling MetadataPropertyHandling - { - get => _serializer.MetadataPropertyHandling; - set => _serializer.MetadataPropertyHandling = value; - } - - public override MissingMemberHandling MissingMemberHandling - { - get => _serializer.MissingMemberHandling; - set => _serializer.MissingMemberHandling = value; - } - - public override NullValueHandling NullValueHandling - { - get => _serializer.NullValueHandling; - set => _serializer.NullValueHandling = value; - } - - public override ObjectCreationHandling ObjectCreationHandling - { - get => _serializer.ObjectCreationHandling; - set => _serializer.ObjectCreationHandling = value; - } - - public override PreserveReferencesHandling PreserveReferencesHandling - { - get => _serializer.PreserveReferencesHandling; - set => _serializer.PreserveReferencesHandling = value; - } - - public override ReferenceLoopHandling ReferenceLoopHandling - { - get => _serializer.ReferenceLoopHandling; - set => _serializer.ReferenceLoopHandling = value; - } - - public override IReferenceResolver? ReferenceResolver - { - get => _serializer.ReferenceResolver; - set => _serializer.ReferenceResolver = value; - } - - public override ISerializationBinder SerializationBinder - { - get => _serializer.SerializationBinder; - set => _serializer.SerializationBinder = value; - } - - public override StringEscapeHandling StringEscapeHandling - { - get => _serializer.StringEscapeHandling; - set => _serializer.StringEscapeHandling = value; - } - - public override ITraceWriter? TraceWriter - { - get => _serializer.TraceWriter; - set => _serializer.TraceWriter = value; - } - - [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] - public override FormatterAssemblyStyle TypeNameAssemblyFormat - { - get => _serializer.TypeNameAssemblyFormat; - set => _serializer.TypeNameAssemblyFormat = value; - } - - public override TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling - { - get => _serializer.TypeNameAssemblyFormatHandling; - set => _serializer.TypeNameAssemblyFormatHandling = value; - } - - public override TypeNameHandling TypeNameHandling - { - get => _serializer.TypeNameHandling; - set => _serializer.TypeNameHandling = value; - } - - public override event EventHandler? Error - { - add => _serializer.Error += value; - remove => _serializer.Error -= value; - } - - internal JsonSerializerInternalBase GetInternalSerializer() - { - if (_serializerReader != null) - return _serializerReader; - - return _serializerWriter!; - } - - internal override object? DeserializeInternal(JsonReader reader, Type? objectType) - { - if (_serializerReader != null) - return _serializerReader.Deserialize(reader, objectType, false); - - return _serializer.Deserialize(reader, objectType); - } - - internal override void PopulateInternal(JsonReader reader, object target) - { - if (_serializerReader != null) - _serializerReader.Populate(reader, target); - else - _serializer.Populate(reader, target); - } - - internal override void SerializeInternal(JsonWriter jsonWriter, object? value, Type? rootType) - { - if (_serializerWriter != null) - _serializerWriter.Serialize(jsonWriter, value, rootType); - else - _serializer.Serialize(jsonWriter, value); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonStringContract.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonStringContract.cs deleted file mode 100644 index a9e499801..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonStringContract.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Contract details for a used by the . - /// - internal class JsonStringContract : JsonPrimitiveContract - { - /// - /// Initializes a new instance of the class. - /// - /// The underlying type for the contract. - public JsonStringContract(Type underlyingType) - : base(underlyingType) => - ContractType = JsonContractType.String; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonTypeReflector.cs deleted file mode 100644 index 59c5d832c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ /dev/null @@ -1,484 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_CAS -using System.Security.Permissions; -#endif -using System; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; -using System.Runtime.Serialization; -using System.Security; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal static class JsonTypeReflector - { - private static bool? _dynamicCodeGeneration; - private static bool? _fullyTrusted; - - public const string IdPropertyName = "$id"; - public const string RefPropertyName = "$ref"; - public const string TypePropertyName = "$type"; - public const string ValuePropertyName = "$value"; - public const string ArrayValuesPropertyName = "$values"; - - public const string ShouldSerializePrefix = "ShouldSerialize"; - public const string SpecifiedPostfix = "Specified"; - - public const string ConcurrentDictionaryTypeName = "System.Collections.Concurrent.ConcurrentDictionary`2"; - - private static readonly ThreadSafeStore> CreatorCache = - new(GetCreator); - -#if !(NET20 || DOTNET) - private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new(GetAssociateMetadataTypeFromAttribute); - private static ReflectionObject? _metadataTypeAttributeReflectionObject; -#endif - - public static T? GetCachedAttribute(object attributeProvider) where T : Attribute => - CachedAttributeGetter.GetAttribute(attributeProvider); - -#if HAVE_TYPE_DESCRIPTOR - public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter typeConverter) - { - typeConverter = TypeDescriptor.GetConverter(type); - - // use the objectType's TypeConverter if it has one and can convert to a string - if (typeConverter != null) - { - Type converterType = typeConverter.GetType(); - - if (!string.Equals(converterType.FullName, "System.ComponentModel.ComponentConverter", StringComparison.Ordinal) - && !string.Equals(converterType.FullName, "System.ComponentModel.ReferenceConverter", StringComparison.Ordinal) - && !string.Equals(converterType.FullName, "System.Windows.Forms.Design.DataSourceConverter", StringComparison.Ordinal) - && converterType != typeof(TypeConverter)) - { - return typeConverter.CanConvertTo(typeof(string)); - } - - } - - return false; - } -#endif - -#if HAVE_DATA_CONTRACTS - public static DataContractAttribute? GetDataContractAttribute(Type type) - { - // DataContractAttribute does not have inheritance - Type currentType = type; - - while (currentType != null) - { - DataContractAttribute? result = CachedAttributeGetter.GetAttribute(currentType); - if (result != null) - { - return result; - } - - currentType = currentType.BaseType(); - } - - return null; - } - - public static DataMemberAttribute? GetDataMemberAttribute(MemberInfo memberInfo) - { - // DataMemberAttribute does not have inheritance - - // can't override a field - if (memberInfo.MemberType() == MemberTypes.Field) - { - return CachedAttributeGetter.GetAttribute(memberInfo); - } - - // search property and then search base properties if nothing is returned and the property is virtual - PropertyInfo propertyInfo = (PropertyInfo)memberInfo; - DataMemberAttribute? result = CachedAttributeGetter.GetAttribute(propertyInfo); - if (result == null) - { - if (propertyInfo.IsVirtual()) - { - Type currentType = propertyInfo.DeclaringType; - - while (result == null && currentType != null) - { - PropertyInfo baseProperty = (PropertyInfo)ReflectionUtils.GetMemberInfoFromType(currentType, propertyInfo); - if (baseProperty != null && baseProperty.IsVirtual()) - { - result = CachedAttributeGetter.GetAttribute(baseProperty); - } - - currentType = currentType.BaseType(); - } - } - } - - return result; - } -#endif - - public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute) - { - var objectAttribute = GetCachedAttribute(objectType); - if (objectAttribute != null) return objectAttribute.MemberSerialization; - -#if HAVE_DATA_CONTRACTS - DataContractAttribute? dataContractAttribute = GetDataContractAttribute(objectType); - if (dataContractAttribute != null) - { - return MemberSerialization.OptIn; - } -#endif - -#if HAVE_BINARY_SERIALIZATION - if (!ignoreSerializableAttribute && IsSerializable(objectType)) - { - return MemberSerialization.Fields; - } -#endif - - // the default - return MemberSerialization.OptOut; - } - - public static JsonConverter? GetJsonConverter(object attributeProvider) - { - var converterAttribute = GetCachedAttribute(attributeProvider); - - if (converterAttribute != null) - { - var creator = CreatorCache.Get(converterAttribute.ConverterType); - if (creator != null) return (JsonConverter)creator(converterAttribute.ConverterParameters); - } - - return null; - } - - /// - /// Lookup and create an instance of the type described by the argument. - /// - /// The type to create. - /// - /// Optional arguments to pass to an initializing constructor of the JsonConverter. - /// If null, the default constructor is used. - /// - public static JsonConverter CreateJsonConverterInstance(Type converterType, object[]? args) - { - var converterCreator = CreatorCache.Get(converterType); - return (JsonConverter)converterCreator(args); - } - - public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyType, object[]? args) - { - var converterCreator = CreatorCache.Get(namingStrategyType); - return (NamingStrategy)converterCreator(args); - } - - public static NamingStrategy? GetContainerNamingStrategy(JsonContainerAttribute containerAttribute) - { - if (containerAttribute.NamingStrategyInstance == null) - { - if (containerAttribute.NamingStrategyType == null) return null; - - containerAttribute.NamingStrategyInstance = - CreateNamingStrategyInstance(containerAttribute.NamingStrategyType, containerAttribute.NamingStrategyParameters); - } - - return containerAttribute.NamingStrategyInstance; - } - - private static Func GetCreator(Type type) - { - var defaultConstructor = ReflectionUtils.HasDefaultConstructor(type, false) - ? ReflectionDelegateFactory.CreateDefaultConstructor(type) - : null; - - return parameters => - { - try - { - if (parameters != null) - { - var paramTypes = parameters.Select(param => - { - if (param == null) throw new InvalidOperationException("Cannot pass a null parameter to the constructor."); - - return param.GetType(); - }) - .ToArray(); - var parameterizedConstructorInfo = type.GetConstructor(paramTypes); - - if (parameterizedConstructorInfo != null) - { - var parameterizedConstructor = ReflectionDelegateFactory.CreateParameterizedConstructor(parameterizedConstructorInfo); - return parameterizedConstructor(parameters); - } - throw new JsonException( - "No matching parameterized constructor found for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); - } - - if (defaultConstructor == null) - throw new JsonException("No parameterless constructor defined for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); - - return defaultConstructor(); - } - catch (Exception ex) - { - throw new JsonException("Error creating '{0}'.".FormatWith(CultureInfo.InvariantCulture, type), ex); - } - }; - } - -#if !(NET20 || DOTNET) - private static Type? GetAssociatedMetadataType(Type type) => AssociatedMetadataTypesCache.Get(type); - - private static Type? GetAssociateMetadataTypeFromAttribute(Type type) - { - var customAttributes = ReflectionUtils.GetAttributes(type, null, true); - - foreach (var attribute in customAttributes) - { - var attributeType = attribute.GetType(); - - // only test on attribute type name - // attribute assembly could change because of type forwarding, etc - if (string.Equals(attributeType.FullName, "System.ComponentModel.DataAnnotations.MetadataTypeAttribute", StringComparison.Ordinal)) - { - const string metadataClassTypeName = "MetadataClassType"; - - if (_metadataTypeAttributeReflectionObject == null) - _metadataTypeAttributeReflectionObject = ReflectionObject.Create(attributeType, metadataClassTypeName); - - return (Type?)_metadataTypeAttributeReflectionObject.GetValue(attribute, metadataClassTypeName); - } - } - - return null; - } -#endif - - private static T? GetAttribute(Type type) where T : Attribute - { - T? attribute; - -#if !(NET20 || DOTNET) - var metadataType = GetAssociatedMetadataType(type); - if (metadataType != null) - { - attribute = ReflectionUtils.GetAttribute(metadataType, true); - if (attribute != null) return attribute; - } -#endif - - attribute = ReflectionUtils.GetAttribute(type, true); - if (attribute != null) return attribute; - - foreach (var typeInterface in type.GetInterfaces()) - { - attribute = ReflectionUtils.GetAttribute(typeInterface, true); - if (attribute != null) return attribute; - } - - return null; - } - - private static T? GetAttribute(MemberInfo memberInfo) where T : Attribute - { - T? attribute; - -#if !(NET20 || DOTNET) - var metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); - if (metadataType != null) - { - var metadataTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(metadataType, memberInfo); - - if (metadataTypeMemberInfo != null) - { - attribute = ReflectionUtils.GetAttribute(metadataTypeMemberInfo, true); - if (attribute != null) return attribute; - } - } -#endif - - attribute = ReflectionUtils.GetAttribute(memberInfo, true); - if (attribute != null) return attribute; - - if (memberInfo.DeclaringType != null) - { - foreach (var typeInterface in memberInfo.DeclaringType.GetInterfaces()) - { - var interfaceTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(typeInterface, memberInfo); - - if (interfaceTypeMemberInfo != null) - { - attribute = ReflectionUtils.GetAttribute(interfaceTypeMemberInfo, true); - if (attribute != null) return attribute; - } - } - } - - return null; - } - -#if HAVE_NON_SERIALIZED_ATTRIBUTE - public static bool IsNonSerializable(object provider) - { -#if HAVE_FULL_REFLECTION - // no inheritance - return (ReflectionUtils.GetAttribute(provider, false) != null); -#else - if (provider is FieldInfo fieldInfo && (fieldInfo.Attributes & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized) - { - return true; - } - - return false; -#endif - } -#endif - -#if HAVE_BINARY_SERIALIZATION - public static bool IsSerializable(object provider) - { -#if HAVE_FULL_REFLECTION - // no inheritance - return (ReflectionUtils.GetAttribute(provider, false) != null); -#else - if (provider is Type type && (type.GetTypeInfo().Attributes & TypeAttributes.Serializable) == TypeAttributes.Serializable) - { - return true; - } - - return false; -#endif - } -#endif - - public static T? GetAttribute(object provider) where T : Attribute - { - if (provider is Type type) return GetAttribute(type); - - if (provider is MemberInfo memberInfo) return GetAttribute(memberInfo); - - return ReflectionUtils.GetAttribute(provider, true); - } - -#if DEBUG - internal static void SetFullyTrusted(bool? fullyTrusted) => _fullyTrusted = fullyTrusted; - - internal static void SetDynamicCodeGeneration(bool dynamicCodeGeneration) => _dynamicCodeGeneration = dynamicCodeGeneration; -#endif - - public static bool DynamicCodeGeneration - { -#if HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE - [SecuritySafeCritical] -#endif - get - { - if (_dynamicCodeGeneration == null) - { -#if HAVE_CAS - try - { - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); - new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess).Demand(); - new SecurityPermission(SecurityPermissionFlag.SkipVerification).Demand(); - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); - new SecurityPermission(PermissionState.Unrestricted).Demand(); - _dynamicCodeGeneration = true; - } - catch (Exception) - { - _dynamicCodeGeneration = false; - } -#else - _dynamicCodeGeneration = false; -#endif - } - - return _dynamicCodeGeneration.GetValueOrDefault(); - } - } - - public static bool FullyTrusted - { - get - { - if (_fullyTrusted == null) - { -#if (DOTNET || PORTABLE || PORTABLE40) - _fullyTrusted = true; -#elif !(NET20 || NET35 || PORTABLE40) - var appDomain = AppDomain.CurrentDomain; - - _fullyTrusted = appDomain.IsHomogenous && appDomain.IsFullyTrusted; -#else - try - { - new SecurityPermission(PermissionState.Unrestricted).Demand(); - _fullyTrusted = true; - } - catch (Exception) - { - _fullyTrusted = false; - } -#endif - } - - return _fullyTrusted.GetValueOrDefault(); - } - } - - public static ReflectionDelegateFactory ReflectionDelegateFactory - { - get - { -#if !(PORTABLE40 || PORTABLE || DOTNET || NET472 || NETSTANDARD2_0 || NET5_0_OR_GREATER) - if (DynamicCodeGeneration) - { - return DynamicReflectionDelegateFactory.Instance; - } - - return LateBoundReflectionDelegateFactory.Instance; -#else - return ExpressionReflectionDelegateFactory.Instance; -#endif - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/KebabCaseNamingStrategy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/KebabCaseNamingStrategy.cs deleted file mode 100644 index b55d699d3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/KebabCaseNamingStrategy.cs +++ /dev/null @@ -1,83 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// A kebab case naming strategy. - /// - internal class KebabCaseNamingStrategy : NamingStrategy - { - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) - { - ProcessDictionaryKeys = processDictionaryKeys; - OverrideSpecifiedNames = overrideSpecifiedNames; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - /// - /// A flag indicating whether extension data names should be processed. - /// - public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) - : this(processDictionaryKeys, overrideSpecifiedNames) => - ProcessExtensionDataNames = processExtensionDataNames; - - /// - /// Initializes a new instance of the class. - /// - public KebabCaseNamingStrategy() { } - - /// - /// Resolves the specified property name. - /// - /// The property name to resolve. - /// The resolved property name. - protected override string ResolvePropertyName(string name) => StringUtils.ToKebabCase(name); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs deleted file mode 100644 index 8f244d950..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Text; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Represents a trace writer that writes to memory. When the trace message limit is - /// reached then old trace messages will be removed as new messages are added. - /// - internal class MemoryTraceWriter : ITraceWriter - { - private readonly object _lock; - private readonly Queue _traceMessages; - - /// - /// Initializes a new instance of the class. - /// - public MemoryTraceWriter() - { - LevelFilter = TraceLevel.Verbose; - _traceMessages = new Queue(); - _lock = new object(); - } - - /// - /// Gets the that will be used to filter the trace messages passed to the writer. - /// For example a filter level of will exclude messages - /// and include , - /// and messages. - /// - /// - /// The that will be used to filter the trace messages passed to the writer. - /// - public TraceLevel LevelFilter { get; set; } - - /// - /// Writes the specified trace level, message and optional exception. - /// - /// The at which to write this trace. - /// The trace message. - /// The trace exception. This parameter is optional. - public void Trace(TraceLevel level, string message, Exception? ex) - { - var sb = new StringBuilder(); - sb.Append(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture)); - sb.Append(" "); - sb.Append(level.ToString("g")); - sb.Append(" "); - sb.Append(message); - - var s = sb.ToString(); - - lock (_lock) - { - if (_traceMessages.Count >= 1000) _traceMessages.Dequeue(); - - _traceMessages.Enqueue(s); - } - } - - /// - /// Returns an enumeration of the most recent trace messages. - /// - /// An enumeration of the most recent trace messages. - public IEnumerable GetTraceMessages() => _traceMessages; - - /// - /// Returns a of the most recent trace messages. - /// - /// - /// A of the most recent trace messages. - /// - public override string ToString() - { - lock (_lock) - { - var sb = new StringBuilder(); - foreach (var traceMessage in _traceMessages) - { - if (sb.Length > 0) sb.AppendLine(); - - sb.Append(traceMessage); - } - - return sb.ToString(); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/NamingStrategy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/NamingStrategy.cs deleted file mode 100644 index 84f7bcbdc..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/NamingStrategy.cs +++ /dev/null @@ -1,137 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// A base class for resolving how property names and dictionary keys are serialized. - /// - internal abstract class NamingStrategy - { - /// - /// Resolves the specified property name. - /// - /// The property name to resolve. - /// The resolved property name. - protected abstract string ResolvePropertyName(string name); - - /// - /// A flag indicating whether explicitly specified property names, - /// e.g. a property name customized with a , should be processed. - /// Defaults to false. - /// - public bool OverrideSpecifiedNames { get; set; } - - /// - /// A flag indicating whether dictionary keys should be processed. - /// Defaults to false. - /// - public bool ProcessDictionaryKeys { get; set; } - - /// - /// A flag indicating whether extension data names should be processed. - /// Defaults to false. - /// - public bool ProcessExtensionDataNames { get; set; } - - /// - /// Gets the serialized name for a given property name. - /// - /// The initial property name. - /// A flag indicating whether the property has had a name explicitly specified. - /// The serialized property name. - public virtual string GetPropertyName(string name, bool hasSpecifiedName) - { - if (hasSpecifiedName && !OverrideSpecifiedNames) return name; - - return ResolvePropertyName(name); - } - - /// - /// Gets the serialized name for a given extension data name. - /// - /// The initial extension data name. - /// The serialized extension data name. - public virtual string GetExtensionDataName(string name) - { - if (!ProcessExtensionDataNames) return name; - - return ResolvePropertyName(name); - } - - /// - /// Gets the serialized key for a given dictionary key. - /// - /// The initial dictionary key. - /// The serialized dictionary key. - public virtual string GetDictionaryKey(string key) - { - if (!ProcessDictionaryKeys) return key; - - return ResolvePropertyName(key); - } - - /// - /// Hash code calculation - /// - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = GetType().GetHashCode(); // make sure different types do not result in equal values - hashCode = (hashCode * 397) ^ ProcessDictionaryKeys.GetHashCode(); - hashCode = (hashCode * 397) ^ ProcessExtensionDataNames.GetHashCode(); - hashCode = (hashCode * 397) ^ OverrideSpecifiedNames.GetHashCode(); - return hashCode; - } - } - - /// - /// Object equality implementation - /// - /// - /// - public override bool Equals(object obj) => Equals(obj as NamingStrategy); - - /// - /// Compare to another NamingStrategy - /// - /// - /// - protected bool Equals(NamingStrategy? other) - { - if (other == null) return false; - - return GetType() == other.GetType() && - ProcessDictionaryKeys == other.ProcessDictionaryKeys && - ProcessExtensionDataNames == other.ProcessExtensionDataNames && - OverrideSpecifiedNames == other.OverrideSpecifiedNames; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ObjectConstructor.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ObjectConstructor.cs deleted file mode 100644 index 2c64243cb..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ObjectConstructor.cs +++ /dev/null @@ -1,36 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Represents a method that constructs an object. - /// - /// The object type to create. - internal delegate object ObjectConstructor(params object?[] args); -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/OnErrorAttribute.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/OnErrorAttribute.cs deleted file mode 100644 index 130b015c7..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/OnErrorAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// When applied to a method, specifies that the method is called when an error occurs serializing an object. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = false)] - internal sealed class OnErrorAttribute : Attribute { } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionAttributeProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionAttributeProvider.cs deleted file mode 100644 index f6de443cd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionAttributeProvider.cs +++ /dev/null @@ -1,73 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Provides methods to get attributes from a , , - /// or . - /// - internal class ReflectionAttributeProvider : IAttributeProvider - { - private readonly object _attributeProvider; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The instance to get attributes for. This parameter should be a - /// , , or . - /// - public ReflectionAttributeProvider(object attributeProvider) - { - ValidationUtils.ArgumentNotNull(attributeProvider, nameof(attributeProvider)); - _attributeProvider = attributeProvider; - } - - /// - /// Returns a collection of all of the attributes, or an empty collection if there are no attributes. - /// - /// When true, look up the hierarchy chain for the inherited custom attribute. - /// A collection of s, or an empty collection. - public IList GetAttributes(bool inherit) => ReflectionUtils.GetAttributes(_attributeProvider, null, inherit); - - /// - /// Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. - /// - /// The type of the attributes. - /// When true, look up the hierarchy chain for the inherited custom attribute. - /// A collection of s, or an empty collection. - public IList GetAttributes(Type attributeType, bool inherit) => - ReflectionUtils.GetAttributes(_attributeProvider, attributeType, inherit); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs deleted file mode 100644 index ed7b28f3b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs +++ /dev/null @@ -1,95 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// Get and set values for a using reflection. - /// - internal class ReflectionValueProvider : IValueProvider - { - private readonly MemberInfo _memberInfo; - - /// - /// Initializes a new instance of the class. - /// - /// The member info. - public ReflectionValueProvider(MemberInfo memberInfo) - { - ValidationUtils.ArgumentNotNull(memberInfo, nameof(memberInfo)); - _memberInfo = memberInfo; - } - - /// - /// Sets the value. - /// - /// The target to set the value on. - /// The value to set on the target. - public void SetValue(object target, object? value) - { - try - { - ReflectionUtils.SetMemberValue(_memberInfo, target, value); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - - /// - /// Gets the value. - /// - /// The target to get the value from. - /// The value. - public object? GetValue(object target) - { - try - { - // https://github.com/dotnet/corefx/issues/26053 - if (_memberInfo is PropertyInfo propertyInfo && propertyInfo.PropertyType.IsByRef) - throw new InvalidOperationException( - "Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, - propertyInfo)); - - return ReflectionUtils.GetMemberValue(_memberInfo, target); - } - catch (Exception ex) - { - throw new JsonSerializationException( - "Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex); - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs deleted file mode 100644 index 58cc38016..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Runtime.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class SerializationBinderAdapter : ISerializationBinder - { -#pragma warning disable 618 - public readonly SerializationBinder SerializationBinder; -#pragma warning restore 618 - -#pragma warning disable 618 - public SerializationBinderAdapter(SerializationBinder serializationBinder) => SerializationBinder = serializationBinder; -#pragma warning restore 618 - - public Type BindToType(string? assemblyName, string typeName) => SerializationBinder.BindToType(assemblyName, typeName); - - public void BindToName(Type serializedType, out string? assemblyName, out string? typeName) - { -#if HAVE_SERIALIZATION_BINDER_BIND_TO_NAME - SerializationBinder.BindToName(serializedType, out assemblyName, out typeName); -#else - assemblyName = null; - typeName = null; -#endif - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SnakeCaseNamingStrategy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SnakeCaseNamingStrategy.cs deleted file mode 100644 index 086b13fdc..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/SnakeCaseNamingStrategy.cs +++ /dev/null @@ -1,83 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - /// - /// A snake case naming strategy. - /// - internal class SnakeCaseNamingStrategy : NamingStrategy - { - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) - { - ProcessDictionaryKeys = processDictionaryKeys; - OverrideSpecifiedNames = overrideSpecifiedNames; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// A flag indicating whether dictionary keys should be processed. - /// - /// - /// A flag indicating whether explicitly specified property names should be processed, - /// e.g. a property name customized with a . - /// - /// - /// A flag indicating whether extension data names should be processed. - /// - public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) - : this(processDictionaryKeys, overrideSpecifiedNames) => - ProcessExtensionDataNames = processExtensionDataNames; - - /// - /// Initializes a new instance of the class. - /// - public SnakeCaseNamingStrategy() { } - - /// - /// Resolves the specified property name. - /// - /// The property name to resolve. - /// The resolved property name. - protected override string ResolvePropertyName(string name) => StringUtils.ToSnakeCase(name); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonReader.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonReader.cs deleted file mode 100644 index 8e22799a9..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonReader.cs +++ /dev/null @@ -1,146 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class TraceJsonReader : JsonReader, IJsonLineInfo - { - private readonly JsonReader _innerReader; - private readonly JsonTextWriter _textWriter; - private readonly StringWriter _sw; - - public TraceJsonReader(JsonReader innerReader) - { - _innerReader = innerReader; - - _sw = new StringWriter(CultureInfo.InvariantCulture); - // prefix the message in the stringwriter to avoid concat with a potentially large JSON string - _sw.Write("Deserialized JSON: " + Environment.NewLine); - - _textWriter = new JsonTextWriter(_sw); - _textWriter.Formatting = Formatting.Indented; - } - - public string GetDeserializedJsonMessage() => _sw.ToString(); - - public override bool Read() - { - var value = _innerReader.Read(); - WriteCurrentToken(); - return value; - } - - public override int? ReadAsInt32() - { - var value = _innerReader.ReadAsInt32(); - WriteCurrentToken(); - return value; - } - - public override string? ReadAsString() - { - var value = _innerReader.ReadAsString(); - WriteCurrentToken(); - return value; - } - - public override byte[]? ReadAsBytes() - { - var value = _innerReader.ReadAsBytes(); - WriteCurrentToken(); - return value; - } - - public override decimal? ReadAsDecimal() - { - var value = _innerReader.ReadAsDecimal(); - WriteCurrentToken(); - return value; - } - - public override double? ReadAsDouble() - { - var value = _innerReader.ReadAsDouble(); - WriteCurrentToken(); - return value; - } - - public override bool? ReadAsBoolean() - { - var value = _innerReader.ReadAsBoolean(); - WriteCurrentToken(); - return value; - } - - public override DateTime? ReadAsDateTime() - { - var value = _innerReader.ReadAsDateTime(); - WriteCurrentToken(); - return value; - } - -#if HAVE_DATE_TIME_OFFSET - public override DateTimeOffset? ReadAsDateTimeOffset() - { - DateTimeOffset? value = _innerReader.ReadAsDateTimeOffset(); - WriteCurrentToken(); - return value; - } -#endif - - public void WriteCurrentToken() => _textWriter.WriteToken(_innerReader, false, false, true); - - public override int Depth => _innerReader.Depth; - - public override string Path => _innerReader.Path; - - public override char QuoteChar - { - get => _innerReader.QuoteChar; - protected internal set => _innerReader.QuoteChar = value; - } - - public override JsonToken TokenType => _innerReader.TokenType; - - public override object? Value => _innerReader.Value; - - public override Type? ValueType => _innerReader.ValueType; - - public override void Close() => _innerReader.Close(); - - bool IJsonLineInfo.HasLineInfo() => _innerReader is IJsonLineInfo lineInfo && lineInfo.HasLineInfo(); - - int IJsonLineInfo.LineNumber => _innerReader is IJsonLineInfo lineInfo ? lineInfo.LineNumber : 0; - - int IJsonLineInfo.LinePosition => _innerReader is IJsonLineInfo lineInfo ? lineInfo.LinePosition : 0; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonWriter.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonWriter.cs deleted file mode 100644 index 0d8268a19..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Serialization/TraceJsonWriter.cs +++ /dev/null @@ -1,525 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; - -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -{ - internal class TraceJsonWriter : JsonWriter - { - private readonly JsonWriter _innerWriter; - private readonly JsonTextWriter _textWriter; - private readonly StringWriter _sw; - - public TraceJsonWriter(JsonWriter innerWriter) - { - _innerWriter = innerWriter; - - _sw = new StringWriter(CultureInfo.InvariantCulture); - // prefix the message in the stringwriter to avoid concat with a potentially large JSON string - _sw.Write("Serialized JSON: " + Environment.NewLine); - - _textWriter = new JsonTextWriter(_sw); - _textWriter.Formatting = Formatting.Indented; - _textWriter.Culture = innerWriter.Culture; - _textWriter.DateFormatHandling = innerWriter.DateFormatHandling; - _textWriter.DateFormatString = innerWriter.DateFormatString; - _textWriter.DateTimeZoneHandling = innerWriter.DateTimeZoneHandling; - _textWriter.FloatFormatHandling = innerWriter.FloatFormatHandling; - } - - public string GetSerializedJsonMessage() => _sw.ToString(); - - public override void WriteValue(decimal value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(decimal? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(bool value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(bool? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(byte value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(byte? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(char value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(char? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(byte[]? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value == null) - base.WriteUndefined(); - else - base.WriteValue(value); - } - - public override void WriteValue(DateTime value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(DateTime? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - -#if HAVE_DATE_TIME_OFFSET - public override void WriteValue(DateTimeOffset value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(DateTimeOffset? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - { - base.WriteValue(value.GetValueOrDefault()); - } - else - { - base.WriteUndefined(); - } - } -#endif - - public override void WriteValue(double value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(double? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteUndefined() - { - _textWriter.WriteUndefined(); - _innerWriter.WriteUndefined(); - base.WriteUndefined(); - } - - public override void WriteNull() - { - _textWriter.WriteNull(); - _innerWriter.WriteNull(); - base.WriteUndefined(); - } - - public override void WriteValue(float value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(float? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(Guid value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(Guid? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(int value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(int? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(long value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(long? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(object? value) - { -#if HAVE_BIG_INTEGER - if (value is BigInteger) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - InternalWriteValue(JsonToken.Integer); - } - else -#endif - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value == null) - base.WriteUndefined(); - else - { - // base.WriteValue(value) will error - InternalWriteValue(JsonToken.String); - } - } - } - - public override void WriteValue(sbyte value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(sbyte? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(short value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(short? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(string? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(TimeSpan value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(TimeSpan? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(uint value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(uint? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(ulong value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(ulong? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteValue(Uri? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value == null) - base.WriteUndefined(); - else - base.WriteValue(value); - } - - public override void WriteValue(ushort value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - base.WriteValue(value); - } - - public override void WriteValue(ushort? value) - { - _textWriter.WriteValue(value); - _innerWriter.WriteValue(value); - if (value.HasValue) - base.WriteValue(value.GetValueOrDefault()); - else - base.WriteUndefined(); - } - - public override void WriteWhitespace(string ws) - { - _textWriter.WriteWhitespace(ws); - _innerWriter.WriteWhitespace(ws); - base.WriteWhitespace(ws); - } - - public override void WriteComment(string? text) - { - _textWriter.WriteComment(text); - _innerWriter.WriteComment(text); - base.WriteComment(text); - } - - public override void WriteStartArray() - { - _textWriter.WriteStartArray(); - _innerWriter.WriteStartArray(); - base.WriteStartArray(); - } - - public override void WriteEndArray() - { - _textWriter.WriteEndArray(); - _innerWriter.WriteEndArray(); - base.WriteEndArray(); - } - - public override void WriteStartConstructor(string name) - { - _textWriter.WriteStartConstructor(name); - _innerWriter.WriteStartConstructor(name); - base.WriteStartConstructor(name); - } - - public override void WriteEndConstructor() - { - _textWriter.WriteEndConstructor(); - _innerWriter.WriteEndConstructor(); - base.WriteEndConstructor(); - } - - public override void WritePropertyName(string name) - { - _textWriter.WritePropertyName(name); - _innerWriter.WritePropertyName(name); - base.WritePropertyName(name); - } - - public override void WritePropertyName(string name, bool escape) - { - _textWriter.WritePropertyName(name, escape); - _innerWriter.WritePropertyName(name, escape); - - // method with escape will error - base.WritePropertyName(name); - } - - public override void WriteStartObject() - { - _textWriter.WriteStartObject(); - _innerWriter.WriteStartObject(); - base.WriteStartObject(); - } - - public override void WriteEndObject() - { - _textWriter.WriteEndObject(); - _innerWriter.WriteEndObject(); - base.WriteEndObject(); - } - - public override void WriteRawValue(string? json) - { - _textWriter.WriteRawValue(json); - _innerWriter.WriteRawValue(json); - - // calling base method will write json twice - InternalWriteValue(JsonToken.Undefined); - } - - public override void WriteRaw(string? json) - { - _textWriter.WriteRaw(json); - _innerWriter.WriteRaw(json); - base.WriteRaw(json); - } - - public override void Close() - { - _textWriter.Close(); - _innerWriter.Close(); - base.Close(); - } - - public override void Flush() - { - _textWriter.Flush(); - _innerWriter.Flush(); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/SerializationBinder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/SerializationBinder.cs deleted file mode 100644 index 9bf22c8e7..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/SerializationBinder.cs +++ /dev/null @@ -1,35 +0,0 @@ -#if (DOTNET || PORTABLE40 || PORTABLE) -using System; -using System.Reflection; - -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Allows users to control class loading and mandate what class to load. - /// - [Obsolete("SerializationBinder is obsolete. Use ISerializationBinder instead.")] - internal abstract class SerializationBinder - { - /// - /// When overridden in a derived class, controls the binding of a serialized object to a type. - /// - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object - /// The type of the object the formatter creates a new instance of. - public abstract Type BindToType(string? assemblyName, string typeName); - - /// - /// When overridden in a derived class, controls the binding of a serialized object to a type. - /// - /// The type of the object the formatter creates a new instance of. - /// Specifies the name of the serialized object. - /// Specifies the name of the serialized object. - public virtual void BindToName(Type serializedType, out string? assemblyName, out string? typeName) - { - assemblyName = null; - typeName = null; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/StringEscapeHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/StringEscapeHandling.cs deleted file mode 100644 index 6187445bf..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/StringEscapeHandling.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies how strings are escaped when writing JSON text. - /// - internal enum StringEscapeHandling - { - /// - /// Only control characters (e.g. newline) are escaped. - /// - Default = 0, - - /// - /// All non-ASCII and control characters (e.g. newline) are escaped. - /// - EscapeNonAscii = 1, - - /// - /// HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. - /// - EscapeHtml = 2 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TraceLevel.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/TraceLevel.cs deleted file mode 100644 index 426059a37..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TraceLevel.cs +++ /dev/null @@ -1,39 +0,0 @@ -#if !HAVE_TRACE_WRITER -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies what messages to output for the class. - /// - internal enum TraceLevel - { - /// - /// Output no tracing and debugging messages. - /// - Off = 0, - - /// - /// Output error-handling messages. - /// - Error = 1, - - /// - /// Output warnings and error-handling messages. - /// - Warning = 2, - - /// - /// Output informational messages, warnings, and error-handling messages. - /// - Info = 3, - - /// - /// Output all debugging and tracing messages. - /// - Verbose = 4 - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameAssemblyFormatHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameAssemblyFormatHandling.cs deleted file mode 100644 index c7f0be2ba..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameAssemblyFormatHandling.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Indicates the method that will be used during deserialization for locating and loading assemblies. - /// - internal enum TypeNameAssemblyFormatHandling - { - /// - /// In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. - /// Specifically, the version numbers need not match as the LoadWithPartialName method of the - /// class is used to load the assembly. - /// - Simple = 0, - - /// - /// In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The - /// Load method of the class is used to load the assembly. - /// - Full = 1 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameHandling.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameHandling.cs deleted file mode 100644 index 453d1e7d3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/TypeNameHandling.cs +++ /dev/null @@ -1,74 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies type name handling options for the . - /// - /// - /// should be used with caution when your application deserializes JSON from - /// an external source. - /// Incoming types should be validated with a custom - /// when deserializing with a value other than . - /// - [Flags] - internal enum TypeNameHandling - { - /// - /// Do not include the .NET type name when serializing types. - /// - None = 0, - - /// - /// Include the .NET type name when serializing into a JSON object structure. - /// - Objects = 1, - - /// - /// Include the .NET type name when serializing into a JSON array structure. - /// - Arrays = 2, - - /// - /// Always include the .NET type name when serializing. - /// - All = Objects | Arrays, - - /// - /// Include the .NET type name when the type of the object being serialized is not the same as its declared type. - /// Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON - /// you must specify a root type object with - /// - /// or . - /// - Auto = 4 - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/AsyncUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/AsyncUtils.cs deleted file mode 100644 index 7fae325f5..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/AsyncUtils.cs +++ /dev/null @@ -1,112 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class AsyncUtils - { - // Pre-allocate to avoid wasted allocations. - public static readonly Task False = Task.FromResult(false); - public static readonly Task True = Task.FromResult(true); - - internal static Task ToAsync(this bool value) => value ? True : False; - - public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) - { - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : null; - } - - public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) - { - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : null; - } - - // From 4.6 on we could use Task.FromCanceled(), but we need an equivalent for - // previous frameworks. - public static Task FromCanceled(this CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(cancellationToken.IsCancellationRequested); - return new Task(() => {}, cancellationToken); - } - - public static Task FromCanceled(this CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(cancellationToken.IsCancellationRequested); -#pragma warning disable CS8603 // Possible null reference return. - return new Task(() => default, cancellationToken); -#pragma warning restore CS8603 // Possible null reference return. - } - - // Task.Delay(0) is optimised as a cached task within the framework, and indeed - // the same cached task that Task.CompletedTask returns as of 4.6, but we'll add - // our own cached field for previous frameworks. - internal static readonly Task CompletedTask = Task.Delay(0); - - public static Task WriteAsync(this TextWriter writer, char value, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(writer != null); - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : writer.WriteAsync(value); - } - - public static Task WriteAsync(this TextWriter writer, string? value, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(writer != null); - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : writer.WriteAsync(value); - } - - public static Task WriteAsync(this TextWriter writer, char[] value, int start, int count, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(writer != null); - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : writer.WriteAsync(value, start, count); - } - - public static Task ReadAsync(this TextReader reader, char[] buffer, int index, int count, CancellationToken cancellationToken) - { - MiscellaneousUtils.Assert(reader != null); - return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : reader.ReadAsync(buffer, index, count); - } - - //TODO typo - public static bool IsCompletedSucessfully(this Task task) - { - // IsCompletedSuccessfully is the faster method, but only currently exposed on .NET Core 2.0 -#if NET8_0_OR_GREATER - return task.IsCompletedSuccessfully; -#else - return task.Status == TaskStatus.RanToCompletion; -#endif - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/Base64Encoder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/Base64Encoder.cs deleted file mode 100644 index 9ba8dc331..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/Base64Encoder.cs +++ /dev/null @@ -1,192 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.IO; - -#if HAVE_ASYNC -using System.Threading; -using System.Threading.Tasks; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class Base64Encoder - { - private const int Base64LineSize = 76; - private const int LineSizeInBytes = 57; - - private readonly char[] _charsLine = new char[Base64LineSize]; - private readonly TextWriter _writer; - - private byte[]? _leftOverBytes; - private int _leftOverBytesCount; - - public Base64Encoder(TextWriter writer) - { - ValidationUtils.ArgumentNotNull(writer, nameof(writer)); - _writer = writer; - } - - private void ValidateEncode(byte[] buffer, int index, int count) - { - if (buffer == null) throw new ArgumentNullException(nameof(buffer)); - - if (index < 0) throw new ArgumentOutOfRangeException(nameof(index)); - - if (count < 0) throw new ArgumentOutOfRangeException(nameof(count)); - - if (count > buffer.Length - index) throw new ArgumentOutOfRangeException(nameof(count)); - } - - public void Encode(byte[] buffer, int index, int count) - { - ValidateEncode(buffer, index, count); - - if (_leftOverBytesCount > 0) - { - if (FulfillFromLeftover(buffer, index, ref count)) return; - - var num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); - WriteChars(_charsLine, 0, num2); - } - - StoreLeftOverBytes(buffer, index, ref count); - - var num4 = index + count; - var length = LineSizeInBytes; - while (index < num4) - { - if (index + length > num4) length = num4 - index; - var num6 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0); - WriteChars(_charsLine, 0, num6); - index += length; - } - } - - private void StoreLeftOverBytes(byte[] buffer, int index, ref int count) - { - var leftOverBytesCount = count % 3; - if (leftOverBytesCount > 0) - { - count -= leftOverBytesCount; - if (_leftOverBytes == null) _leftOverBytes = new byte[3]; - - for (var i = 0; i < leftOverBytesCount; i++) _leftOverBytes[i] = buffer[index + count + i]; - } - - _leftOverBytesCount = leftOverBytesCount; - } - - private bool FulfillFromLeftover(byte[] buffer, int index, ref int count) - { - var leftOverBytesCount = _leftOverBytesCount; - while (leftOverBytesCount < 3 && count > 0) - { - _leftOverBytes![leftOverBytesCount++] = buffer[index++]; - count--; - } - - if (count == 0 && leftOverBytesCount < 3) - { - _leftOverBytesCount = leftOverBytesCount; - return true; - } - - return false; - } - - public void Flush() - { - if (_leftOverBytesCount > 0) - { - var count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); - WriteChars(_charsLine, 0, count); - _leftOverBytesCount = 0; - } - } - - private void WriteChars(char[] chars, int index, int count) => _writer.Write(chars, index, count); - -#if HAVE_ASYNC - public async Task EncodeAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken) - { - ValidateEncode(buffer, index, count); - - if (_leftOverBytesCount > 0) - { - if (FulfillFromLeftover(buffer, index, ref count)) - { - return; - } - - int num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); - await WriteCharsAsync(_charsLine, 0, num2, cancellationToken).ConfigureAwait(false); - } - - StoreLeftOverBytes(buffer, index, ref count); - - int num4 = index + count; - int length = LineSizeInBytes; - while (index < num4) - { - if (index + length > num4) - { - length = num4 - index; - } - int num6 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0); - await WriteCharsAsync(_charsLine, 0, num6, cancellationToken).ConfigureAwait(false); - index += length; - } - } - - private Task WriteCharsAsync(char[] chars, int index, int count, CancellationToken cancellationToken) - { - return _writer.WriteAsync(chars, index, count, cancellationToken); - } - - public Task FlushAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - if (_leftOverBytesCount > 0) - { - int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); - _leftOverBytesCount = 0; - return WriteCharsAsync(_charsLine, 0, count, cancellationToken); - } - - return AsyncUtils.CompletedTask; - } - -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs deleted file mode 100644 index 03fc23a1a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class BidirectionalDictionary - { - private readonly string _duplicateFirstErrorMessage; - private readonly string _duplicateSecondErrorMessage; - private readonly IDictionary _firstToSecond; - private readonly IDictionary _secondToFirst; - - public BidirectionalDictionary() - : this(EqualityComparer.Default, EqualityComparer.Default) { } - - public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer) - : this( - firstEqualityComparer, - secondEqualityComparer, - "Duplicate item already exists for '{0}'.", - "Duplicate item already exists for '{0}'.") { } - - public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer, - string duplicateFirstErrorMessage, string duplicateSecondErrorMessage - ) - { - _firstToSecond = new Dictionary(firstEqualityComparer); - _secondToFirst = new Dictionary(secondEqualityComparer); - _duplicateFirstErrorMessage = duplicateFirstErrorMessage; - _duplicateSecondErrorMessage = duplicateSecondErrorMessage; - } - - public void Set(TFirst first, TSecond second) - { - if (_firstToSecond.TryGetValue(first, out var existingSecond)) - { - if (!existingSecond!.Equals(second)) - throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first)); - } - - if (_secondToFirst.TryGetValue(second, out var existingFirst)) - { - if (!existingFirst!.Equals(first)) - throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second)); - } - - _firstToSecond.Add(first, second); - _secondToFirst.Add(second, first); - } - - public bool TryGetByFirst(TFirst first, out TSecond second) => _firstToSecond.TryGetValue(first, out second); - - public bool TryGetBySecond(TSecond second, out TFirst first) => _secondToFirst.TryGetValue(second, out first); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionUtils.cs deleted file mode 100644 index d57fa74f4..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionUtils.cs +++ /dev/null @@ -1,307 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif -#if HAVE_METHOD_IMPL_ATTRIBUTE -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class CollectionUtils - { - /// - /// Determines whether the collection is null or empty. - /// - /// The collection. - /// - /// true if the collection is null or empty; otherwise, false. - /// - public static bool IsNullOrEmpty(ICollection collection) - { - if (collection != null) return collection.Count == 0; - - return true; - } - - /// - /// Adds the elements of the specified collection to the specified generic . - /// - /// The list to add to. - /// The collection of elements to add. - public static void AddRange(this IList initial, IEnumerable collection) - { - if (initial == null) throw new ArgumentNullException(nameof(initial)); - - if (collection == null) return; - - foreach (var value in collection) initial.Add(value); - } - -#if !HAVE_COVARIANT_GENERICS - public static void AddRange(this IList initial, IEnumerable collection) - { - ValidationUtils.ArgumentNotNull(initial, nameof(initial)); - - // because earlier versions of .NET didn't support covariant generics - initial.AddRange(collection.Cast()); - } -#endif - - public static bool IsDictionaryType(Type type) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - - if (typeof(IDictionary).IsAssignableFrom(type)) return true; - - if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<,>))) return true; -#if HAVE_READ_ONLY_COLLECTIONS - if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IReadOnlyDictionary<,>))) - { - return true; - } -#endif - - return false; - } - - public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) - { - var genericConstructorArgument = typeof(IList<>).MakeGenericType(collectionItemType); - - return ResolveEnumerableCollectionConstructor(collectionType, collectionItemType, genericConstructorArgument); - } - - public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, - Type constructorArgumentType - ) - { - var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType); - ConstructorInfo? match = null; - - foreach (var constructor in collectionType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)) - { - IList parameters = constructor.GetParameters(); - - if (parameters.Count == 1) - { - var parameterType = parameters[0].ParameterType; - - if (genericEnumerable == parameterType) - { - // exact match - match = constructor; - break; - } - - // in case we can't find an exact match, use first inexact - if (match == null) - if (parameterType.IsAssignableFrom(constructorArgumentType)) - match = constructor; - } - } - - return match; - } - - public static bool AddDistinct(this IList list, T value) => list.AddDistinct(value, EqualityComparer.Default); - - public static bool AddDistinct(this IList list, T value, IEqualityComparer comparer) - { - if (list.ContainsValue(value, comparer)) return false; - - list.Add(value); - return true; - } - - // this is here because LINQ Bridge doesn't support Contains with IEqualityComparer - public static bool ContainsValue(this IEnumerable source, TSource value, IEqualityComparer comparer) - { - if (comparer == null) comparer = EqualityComparer.Default; - - if (source == null) throw new ArgumentNullException(nameof(source)); - - foreach (var local in source) - if (comparer.Equals(local, value)) - return true; - - return false; - } - - public static bool AddRangeDistinct(this IList list, IEnumerable values, IEqualityComparer comparer) - { - var allAdded = true; - foreach (var value in values) - if (!list.AddDistinct(value, comparer)) - allAdded = false; - - return allAdded; - } - - public static int IndexOf(this IEnumerable collection, Func predicate) - { - var index = 0; - foreach (var value in collection) - { - if (predicate(value)) return index; - - index++; - } - - return -1; - } - - public static bool Contains(this List list, T value, IEqualityComparer comparer) - { - for (var i = 0; i < list.Count; i++) - if (comparer.Equals(value, list[i])) - return true; - - return false; - } - - public static int IndexOfReference(this List list, T item) - { - for (var i = 0; i < list.Count; i++) - if (ReferenceEquals(item, list[i])) - return i; - - return -1; - } - -#if HAVE_FAST_REVERSE - // faster reverse in .NET Framework with value types - https://github.com/JamesNK/Newtonsoft.Json/issues/1430 - public static void FastReverse(this List list) - { - int i = 0; - int j = list.Count - 1; - while (i < j) - { - T temp = list[i]; - list[i] = list[j]; - list[j] = temp; - i++; - j--; - } - } -#endif - - private static IList GetDimensions(IList values, int dimensionsCount) - { - IList dimensions = new List(); - - var currentArray = values; - while (true) - { - dimensions.Add(currentArray.Count); - - // don't keep calculating dimensions for arrays inside the value array - if (dimensions.Count == dimensionsCount) break; - - if (currentArray.Count == 0) break; - - var v = currentArray[0]; - if (v is IList list) - currentArray = list; - else - break; - } - - return dimensions; - } - - private static void CopyFromJaggedToMultidimensionalArray(IList values, Array multidimensionalArray, int[] indices) - { - var dimension = indices.Length; - if (dimension == multidimensionalArray.Rank) - { - multidimensionalArray.SetValue(JaggedArrayGetValue(values, indices), indices); - return; - } - - var dimensionLength = multidimensionalArray.GetLength(dimension); - var list = (IList)JaggedArrayGetValue(values, indices); - var currentValuesLength = list.Count; - if (currentValuesLength != dimensionLength) throw new Exception("Cannot deserialize non-cubical array as multidimensional array."); - - var newIndices = new int[dimension + 1]; - for (var i = 0; i < dimension; i++) newIndices[i] = indices[i]; - - for (var i = 0; i < multidimensionalArray.GetLength(dimension); i++) - { - newIndices[dimension] = i; - CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, newIndices); - } - } - - private static object JaggedArrayGetValue(IList values, int[] indices) - { - var currentList = values; - for (var i = 0; i < indices.Length; i++) - { - var index = indices[i]; - if (i == indices.Length - 1) - return currentList[index]; - - currentList = (IList)currentList[index]; - } - return currentList; - } - - public static Array ToMultidimensionalArray(IList values, Type type, int rank) - { - var dimensions = GetDimensions(values, rank); - - while (dimensions.Count < rank) dimensions.Add(0); - - var multidimensionalArray = Array.CreateInstance(type, dimensions.ToArray()); - CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, ArrayEmpty()); - - return multidimensionalArray; - } - - public static T[] ArrayEmpty() => - // Enumerable.Empty no longer returns an empty array in .NET Core 3.0 - EmptyArrayContainer.Empty; - - private static class EmptyArrayContainer - { -#pragma warning disable CA1825 // Avoid zero-length array allocations. - public static readonly T[] Empty = new T[0]; -#pragma warning restore CA1825 // Avoid zero-length array allocations. - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionWrapper.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionWrapper.cs deleted file mode 100644 index de4fdf911..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/CollectionWrapper.cs +++ /dev/null @@ -1,250 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Threading; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal interface IWrappedCollection : IList - { - object UnderlyingCollection { get; } - } - - internal class CollectionWrapper : ICollection, IWrappedCollection - { - private readonly ICollection? _genericCollection; - private readonly IList? _list; - - public CollectionWrapper(IList list) - { - ValidationUtils.ArgumentNotNull(list, nameof(list)); - - if (list is ICollection collection) - _genericCollection = collection; - else - _list = list; - } - - public CollectionWrapper(ICollection list) - { - ValidationUtils.ArgumentNotNull(list, nameof(list)); - - _genericCollection = list; - } - - private object? _syncRoot; - - public virtual int Count - { - get - { - if (_genericCollection != null) - return _genericCollection.Count; - - return _list!.Count; - } - } - - bool IList.IsFixedSize - { - get - { - if (_genericCollection != null) - { - // ICollection only has IsReadOnly - return _genericCollection.IsReadOnly; - } - return _list!.IsFixedSize; - } - } - - public virtual bool IsReadOnly - { - get - { - if (_genericCollection != null) - return _genericCollection.IsReadOnly; - - return _list!.IsReadOnly; - } - } - - bool ICollection.IsSynchronized => false; - - object IList.this[int index] - { - get - { - if (_genericCollection != null) throw new InvalidOperationException("Wrapped ICollection does not support indexer."); - - return _list![index]; - } - set - { - if (_genericCollection != null) throw new InvalidOperationException("Wrapped ICollection does not support indexer."); - - VerifyValueType(value); - _list![index] = (T)value; - } - } - - object ICollection.SyncRoot - { - get - { - if (_syncRoot == null) Interlocked.CompareExchange(ref _syncRoot, new object(), null); - - return _syncRoot; - } - } - - public object UnderlyingCollection => (object)_genericCollection! ?? _list!; - - public virtual void Add(T item) - { - if (_genericCollection != null) - _genericCollection.Add(item); - else - _list!.Add(item); - } - - public virtual void Clear() - { - if (_genericCollection != null) - _genericCollection.Clear(); - else - _list!.Clear(); - } - - public virtual bool Contains(T item) - { - if (_genericCollection != null) - return _genericCollection.Contains(item); - - return _list!.Contains(item); - } - - public virtual void CopyTo(T[] array, int arrayIndex) - { - if (_genericCollection != null) - _genericCollection.CopyTo(array, arrayIndex); - else - _list!.CopyTo(array, arrayIndex); - } - - public virtual bool Remove(T item) - { - if (_genericCollection != null) - return _genericCollection.Remove(item); - - var contains = _list!.Contains(item); - - if (contains) _list!.Remove(item); - - return contains; - } - - public virtual IEnumerator GetEnumerator() => (_genericCollection ?? _list.Cast()).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_genericCollection! ?? _list!).GetEnumerator(); - - int IList.Add(object value) - { - VerifyValueType(value); - Add((T)value); - - return Count - 1; - } - - bool IList.Contains(object value) - { - if (IsCompatibleObject(value)) return Contains((T)value); - - return false; - } - - int IList.IndexOf(object value) - { - if (_genericCollection != null) throw new InvalidOperationException("Wrapped ICollection does not support IndexOf."); - - if (IsCompatibleObject(value)) return _list!.IndexOf((T)value); - - return -1; - } - - void IList.RemoveAt(int index) - { - if (_genericCollection != null) throw new InvalidOperationException("Wrapped ICollection does not support RemoveAt."); - - _list!.RemoveAt(index); - } - - void IList.Insert(int index, object value) - { - if (_genericCollection != null) throw new InvalidOperationException("Wrapped ICollection does not support Insert."); - - VerifyValueType(value); - _list!.Insert(index, (T)value); - } - - void IList.Remove(object value) - { - if (IsCompatibleObject(value)) Remove((T)value); - } - - void ICollection.CopyTo(Array array, int arrayIndex) => CopyTo((T[])array, arrayIndex); - - private static void VerifyValueType(object value) - { - if (!IsCompatibleObject(value)) - { - throw new ArgumentException( - "The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, - value, typeof(T)), nameof(value)); - } - } - - private static bool IsCompatibleObject(object value) - { - if (!(value is T) && (value != null || typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T)))) return false; - - return true; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ConvertUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ConvertUtils.cs deleted file mode 100644 index 672f15c8a..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ /dev/null @@ -1,1444 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_GUID_TRY_PARSE -using System.Text.RegularExpressions; - -#endif -#if !HAVE_LINQ - -#endif -#if HAVE_ADO_NET - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal enum PrimitiveTypeCode - { - Empty = 0, - Object = 1, - Char = 2, - CharNullable = 3, - Boolean = 4, - BooleanNullable = 5, - SByte = 6, - SByteNullable = 7, - Int16 = 8, - Int16Nullable = 9, - UInt16 = 10, - UInt16Nullable = 11, - Int32 = 12, - Int32Nullable = 13, - Byte = 14, - ByteNullable = 15, - UInt32 = 16, - UInt32Nullable = 17, - Int64 = 18, - Int64Nullable = 19, - UInt64 = 20, - UInt64Nullable = 21, - Single = 22, - SingleNullable = 23, - Double = 24, - DoubleNullable = 25, - DateTime = 26, - DateTimeNullable = 27, - DateTimeOffset = 28, - DateTimeOffsetNullable = 29, - Decimal = 30, - DecimalNullable = 31, - Guid = 32, - GuidNullable = 33, - TimeSpan = 34, - TimeSpanNullable = 35, - BigInteger = 36, - BigIntegerNullable = 37, - Uri = 38, - String = 39, - Bytes = 40, - DBNull = 41 - } - - internal class TypeInformation - { - public TypeInformation(Type type, PrimitiveTypeCode typeCode) - { - Type = type; - TypeCode = typeCode; - } - - public Type Type { get; } - public PrimitiveTypeCode TypeCode { get; } - } - - internal enum ParseResult - { - None = 0, - Success = 1, - Overflow = 2, - Invalid = 3 - } - - internal static class ConvertUtils - { - private static readonly Dictionary TypeCodeMap = - new() - { - { typeof(char), PrimitiveTypeCode.Char }, - { typeof(char?), PrimitiveTypeCode.CharNullable }, - { typeof(bool), PrimitiveTypeCode.Boolean }, - { typeof(bool?), PrimitiveTypeCode.BooleanNullable }, - { typeof(sbyte), PrimitiveTypeCode.SByte }, - { typeof(sbyte?), PrimitiveTypeCode.SByteNullable }, - { typeof(short), PrimitiveTypeCode.Int16 }, - { typeof(short?), PrimitiveTypeCode.Int16Nullable }, - { typeof(ushort), PrimitiveTypeCode.UInt16 }, - { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable }, - { typeof(int), PrimitiveTypeCode.Int32 }, - { typeof(int?), PrimitiveTypeCode.Int32Nullable }, - { typeof(byte), PrimitiveTypeCode.Byte }, - { typeof(byte?), PrimitiveTypeCode.ByteNullable }, - { typeof(uint), PrimitiveTypeCode.UInt32 }, - { typeof(uint?), PrimitiveTypeCode.UInt32Nullable }, - { typeof(long), PrimitiveTypeCode.Int64 }, - { typeof(long?), PrimitiveTypeCode.Int64Nullable }, - { typeof(ulong), PrimitiveTypeCode.UInt64 }, - { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable }, - { typeof(float), PrimitiveTypeCode.Single }, - { typeof(float?), PrimitiveTypeCode.SingleNullable }, - { typeof(double), PrimitiveTypeCode.Double }, - { typeof(double?), PrimitiveTypeCode.DoubleNullable }, - { typeof(DateTime), PrimitiveTypeCode.DateTime }, - { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable }, -#if HAVE_DATE_TIME_OFFSET - { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset }, - { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable }, -#endif - { typeof(decimal), PrimitiveTypeCode.Decimal }, - { typeof(decimal?), PrimitiveTypeCode.DecimalNullable }, - { typeof(Guid), PrimitiveTypeCode.Guid }, - { typeof(Guid?), PrimitiveTypeCode.GuidNullable }, - { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan }, - { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable }, -#if HAVE_BIG_INTEGER - { typeof(BigInteger), PrimitiveTypeCode.BigInteger }, - { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable }, -#endif - { typeof(Uri), PrimitiveTypeCode.Uri }, - { typeof(string), PrimitiveTypeCode.String }, - { typeof(byte[]), PrimitiveTypeCode.Bytes }, -#if HAVE_ADO_NET - { typeof(DBNull), PrimitiveTypeCode.DBNull } -#endif - }; - -#if HAVE_ICONVERTIBLE - private static readonly TypeInformation[] PrimitiveTypeCodes = - { - // need all of these. lookup against the index with TypeCode value - new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), - new TypeInformation(typeof(object), PrimitiveTypeCode.Object), - new TypeInformation(typeof(object), PrimitiveTypeCode.DBNull), - new TypeInformation(typeof(bool), PrimitiveTypeCode.Boolean), - new TypeInformation(typeof(char), PrimitiveTypeCode.Char), - new TypeInformation(typeof(sbyte), PrimitiveTypeCode.SByte), - new TypeInformation(typeof(byte), PrimitiveTypeCode.Byte), - new TypeInformation(typeof(short), PrimitiveTypeCode.Int16), - new TypeInformation(typeof(ushort), PrimitiveTypeCode.UInt16), - new TypeInformation(typeof(int), PrimitiveTypeCode.Int32), - new TypeInformation(typeof(uint), PrimitiveTypeCode.UInt32), - new TypeInformation(typeof(long), PrimitiveTypeCode.Int64), - new TypeInformation(typeof(ulong), PrimitiveTypeCode.UInt64), - new TypeInformation(typeof(float), PrimitiveTypeCode.Single), - new TypeInformation(typeof(double), PrimitiveTypeCode.Double), - new TypeInformation(typeof(decimal), PrimitiveTypeCode.Decimal), - new TypeInformation(typeof(DateTime), PrimitiveTypeCode.DateTime), - new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), // no 17 in TypeCode for some reason - new TypeInformation(typeof(string), PrimitiveTypeCode.String) - }; -#endif - - public static PrimitiveTypeCode GetTypeCode(Type t) => GetTypeCode(t, out _); - - public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum) - { - if (TypeCodeMap.TryGetValue(t, out var typeCode)) - { - isEnum = false; - return typeCode; - } - - if (t.IsEnum()) - { - isEnum = true; - return GetTypeCode(Enum.GetUnderlyingType(t)); - } - - // performance? - if (ReflectionUtils.IsNullableType(t)) - { - var nonNullable = Nullable.GetUnderlyingType(t); - if (nonNullable.IsEnum()) - { - var nullableUnderlyingType = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(nonNullable)); - isEnum = true; - return GetTypeCode(nullableUnderlyingType); - } - } - - isEnum = false; - return PrimitiveTypeCode.Object; - } - -#if HAVE_ICONVERTIBLE - public static TypeInformation GetTypeInformation(IConvertible convertable) - { - TypeInformation typeInformation = PrimitiveTypeCodes[(int)convertable.GetTypeCode()]; - return typeInformation; - } -#endif - - public static bool IsConvertible(Type t) => -#if HAVE_ICONVERTIBLE - typeof(IConvertible).IsAssignableFrom(t); -#else - t == typeof(bool) || t == typeof(byte) || t == typeof(char) || t == typeof(DateTime) || t == typeof(decimal) || t == typeof(double) - || t == typeof(short) || t == typeof(int) || - t == typeof(long) || t == typeof(sbyte) || t == typeof(float) || t == typeof(string) || t == typeof(ushort) || t == typeof(uint) - || t == typeof(ulong) || t.IsEnum(); -#endif - - - public static TimeSpan ParseTimeSpan(string input) => -#if HAVE_TIME_SPAN_PARSE_WITH_CULTURE - TimeSpan.Parse(input, CultureInfo.InvariantCulture); -#else - TimeSpan.Parse(input); -#endif - - - private static readonly ThreadSafeStore, Func?> CastConverters = - new(CreateCastConverter); - - private static Func? CreateCastConverter(StructMultiKey t) - { - var initialType = t.Value1; - var targetType = t.Value2; - var castMethodInfo = targetType.GetMethod("op_Implicit", new[] { initialType }) - ?? targetType.GetMethod("op_Explicit", new[] { initialType }); - - if (castMethodInfo == null) return null; - - var call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(castMethodInfo); - - return o => call(null, o); - } - -#if HAVE_BIG_INTEGER - internal static BigInteger ToBigInteger(object value) - { - if (value is BigInteger integer) - { - return integer; - } - - if (value is string s) - { - return BigInteger.Parse(s, CultureInfo.InvariantCulture); - } - - if (value is float f) - { - return new BigInteger(f); - } - if (value is double d) - { - return new BigInteger(d); - } - if (value is decimal @decimal) - { - return new BigInteger(@decimal); - } - if (value is int i) - { - return new BigInteger(i); - } - if (value is long l) - { - return new BigInteger(l); - } - if (value is uint u) - { - return new BigInteger(u); - } - if (value is ulong @ulong) - { - return new BigInteger(@ulong); - } - - if (value is byte[] bytes) - { - return new BigInteger(bytes); - } - - throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); - } - - public static object FromBigInteger(BigInteger i, Type targetType) - { - if (targetType == typeof(decimal)) - { - return (decimal)i; - } - if (targetType == typeof(double)) - { - return (double)i; - } - if (targetType == typeof(float)) - { - return (float)i; - } - if (targetType == typeof(ulong)) - { - return (ulong)i; - } - if (targetType == typeof(bool)) - { - return i != 0; - } - - try - { - return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture); - } - catch (Exception ex) - { - throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), ex); - } - } -#endif - - #region TryConvert - - internal enum ConvertResult - { - Success = 0, - CannotConvertNull = 1, - NotInstantiableType = 2, - NoValidConversion = 3 - } - - public static object Convert(object initialValue, CultureInfo culture, Type targetType) - { - switch (TryConvertInternal(initialValue, culture, targetType, out var value)) - { - case ConvertResult.Success: - return value!; - case ConvertResult.CannotConvertNull: - throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, - initialValue.GetType(), targetType)); - case ConvertResult.NotInstantiableType: - throw new ArgumentException( - "Target type {0} is not a value type or a non-abstract class.".FormatWith(CultureInfo.InvariantCulture, targetType), - nameof(targetType)); - case ConvertResult.NoValidConversion: - throw new InvalidOperationException( - "Can not convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)); - default: - throw new InvalidOperationException("Unexpected conversion result."); - } - } - - private static bool TryConvert(object? initialValue, CultureInfo culture, Type targetType, out object? value) - { - try - { - if (TryConvertInternal(initialValue, culture, targetType, out value) == ConvertResult.Success) return true; - - value = null; - return false; - } - catch - { - value = null; - return false; - } - } - - private static ConvertResult TryConvertInternal(object? initialValue, CultureInfo culture, Type targetType, out object? value) - { - if (initialValue == null) throw new ArgumentNullException(nameof(initialValue)); - - if (ReflectionUtils.IsNullableType(targetType)) targetType = Nullable.GetUnderlyingType(targetType); - - var initialType = initialValue.GetType(); - - if (targetType == initialType) - { - value = initialValue; - return ConvertResult.Success; - } - - // use Convert.ChangeType if both types are IConvertible - if (IsConvertible(initialValue.GetType()) && IsConvertible(targetType)) - { - if (targetType.IsEnum()) - { - if (initialValue is string) - { - value = Enum.Parse(targetType, initialValue.ToString(), true); - return ConvertResult.Success; - } - if (IsInteger(initialValue)) - { - value = Enum.ToObject(targetType, initialValue); - return ConvertResult.Success; - } - } - - value = System.Convert.ChangeType(initialValue, targetType, culture); - return ConvertResult.Success; - } - -#if HAVE_DATE_TIME_OFFSET - if (initialValue is DateTime dt && targetType == typeof(DateTimeOffset)) - { - value = new DateTimeOffset(dt); - return ConvertResult.Success; - } -#endif - - if (initialValue is byte[] bytes && targetType == typeof(Guid)) - { - value = new Guid(bytes); - return ConvertResult.Success; - } - - if (initialValue is Guid guid && targetType == typeof(byte[])) - { - value = guid.ToByteArray(); - return ConvertResult.Success; - } - - if (initialValue is string s) - { - if (targetType == typeof(Guid)) - { - value = new Guid(s); - return ConvertResult.Success; - } - if (targetType == typeof(Uri)) - { - value = new Uri(s, UriKind.RelativeOrAbsolute); - return ConvertResult.Success; - } - if (targetType == typeof(TimeSpan)) - { - value = ParseTimeSpan(s); - return ConvertResult.Success; - } - if (targetType == typeof(byte[])) - { - value = System.Convert.FromBase64String(s); - return ConvertResult.Success; - } - if (targetType == typeof(Version)) - { - if (VersionTryParse(s, out var result)) - { - value = result; - return ConvertResult.Success; - } - value = null; - return ConvertResult.NoValidConversion; - } - if (typeof(Type).IsAssignableFrom(targetType)) - { - value = Type.GetType(s, true); - return ConvertResult.Success; - } - } - -#if HAVE_BIG_INTEGER - if (targetType == typeof(BigInteger)) - { - value = ToBigInteger(initialValue); - return ConvertResult.Success; - } - if (initialValue is BigInteger integer) - { - value = FromBigInteger(integer, targetType); - return ConvertResult.Success; - } -#endif - -#if HAVE_TYPE_DESCRIPTOR - // see if source or target types have a TypeConverter that converts between the two - TypeConverter toConverter = TypeDescriptor.GetConverter(initialType); - - if (toConverter != null && toConverter.CanConvertTo(targetType)) - { - value = toConverter.ConvertTo(null, culture, initialValue, targetType); - return ConvertResult.Success; - } - - TypeConverter fromConverter = TypeDescriptor.GetConverter(targetType); - - if (fromConverter != null && fromConverter.CanConvertFrom(initialType)) - { - value = fromConverter.ConvertFrom(null, culture, initialValue); - return ConvertResult.Success; - } -#endif -#if HAVE_ADO_NET - // handle DBNull - if (initialValue == DBNull.Value) - { - if (ReflectionUtils.IsNullable(targetType)) - { - value = EnsureTypeAssignable(null, initialType, targetType); - return ConvertResult.Success; - } - - // cannot convert null to non-nullable - value = null; - return ConvertResult.CannotConvertNull; - } -#endif - - if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract()) - { - value = null; - return ConvertResult.NotInstantiableType; - } - - value = null; - return ConvertResult.NoValidConversion; - } - - #endregion - - #region ConvertOrCast - - /// - /// Converts the value to the specified type. If the value is unable to be converted, the - /// value is checked whether it assignable to the specified type. - /// - /// The value to convert. - /// The culture to use when converting. - /// The type to convert or cast the value to. - /// - /// The converted type. If conversion was unsuccessful, the initial value - /// is returned if assignable to the target type. - /// - public static object? ConvertOrCast(object? initialValue, CultureInfo culture, Type targetType) - { - if (targetType == typeof(object)) return initialValue; - - if (initialValue == null && ReflectionUtils.IsNullable(targetType)) return null; - - if (TryConvert(initialValue, culture, targetType, out var convertedValue)) return convertedValue; - - return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue)!, targetType); - } - - #endregion - - private static object? EnsureTypeAssignable(object? value, Type initialType, Type targetType) - { - if (value != null) - { - var valueType = value.GetType(); - - if (targetType.IsAssignableFrom(valueType)) return value; - - var castConverter = CastConverters.Get(new StructMultiKey(valueType, targetType)); - if (castConverter != null) return castConverter(value); - } - else - { - if (ReflectionUtils.IsNullable(targetType)) return null; - } - - throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, - initialType?.ToString() ?? "{null}", targetType)); - } - - public static bool VersionTryParse(string input, [NotNullWhen(true)] out Version? result) - { -#if HAVE_VERSION_TRY_PARSE - return Version.TryParse(input, out result); -#else - // improve failure performance with regex? - try - { - result = new Version(input); - return true; - } - catch - { - result = null; - return false; - } -#endif - } - - public static bool IsInteger(object value) - { - switch (GetTypeCode(value.GetType())) - { - case PrimitiveTypeCode.SByte: - case PrimitiveTypeCode.Byte: - case PrimitiveTypeCode.Int16: - case PrimitiveTypeCode.UInt16: - case PrimitiveTypeCode.Int32: - case PrimitiveTypeCode.UInt32: - case PrimitiveTypeCode.Int64: - case PrimitiveTypeCode.UInt64: - return true; - default: - return false; - } - } - - public static ParseResult Int32TryParse(char[] chars, int start, int length, out int value) - { - value = 0; - - if (length == 0) return ParseResult.Invalid; - - var isNegative = chars[start] == '-'; - - if (isNegative) - { - // text just a negative sign - if (length == 1) return ParseResult.Invalid; - - start++; - length--; - } - - var end = start + length; - - // Int32.MaxValue and MinValue are 10 chars - // Or is 10 chars and start is greater than two - // Need to improve this! - if (length > 10 || length == 10 && chars[start] - '0' > 2) - { - // invalid result takes precedence over overflow - for (var i = start; i < end; i++) - { - var c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - } - - return ParseResult.Overflow; - } - - for (var i = start; i < end; i++) - { - var c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - - var newValue = 10 * value - c; - - // overflow has caused the number to loop around - if (newValue > value) - { - i++; - - // double check the rest of the string that there wasn't anything invalid - // invalid result takes precedence over overflow result - for (; i < end; i++) - { - c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - } - - return ParseResult.Overflow; - } - - value = newValue; - } - - // go from negative to positive to avoids overflow - // negative can be slightly bigger than positive - if (!isNegative) - { - // negative integer can be one bigger than positive - if (value == int.MinValue) return ParseResult.Overflow; - - value = -value; - } - - return ParseResult.Success; - } - - public static ParseResult Int64TryParse(char[] chars, int start, int length, out long value) - { - value = 0; - - if (length == 0) return ParseResult.Invalid; - - var isNegative = chars[start] == '-'; - - if (isNegative) - { - // text just a negative sign - if (length == 1) return ParseResult.Invalid; - - start++; - length--; - } - - var end = start + length; - - // Int64.MaxValue and MinValue are 19 chars - if (length > 19) - { - // invalid result takes precedence over overflow - for (var i = start; i < end; i++) - { - var c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - } - - return ParseResult.Overflow; - } - - for (var i = start; i < end; i++) - { - var c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - - var newValue = 10 * value - c; - - // overflow has caused the number to loop around - if (newValue > value) - { - i++; - - // double check the rest of the string that there wasn't anything invalid - // invalid result takes precedence over overflow result - for (; i < end; i++) - { - c = chars[i] - '0'; - - if (c < 0 || c > 9) return ParseResult.Invalid; - } - - return ParseResult.Overflow; - } - - value = newValue; - } - - // go from negative to positive to avoids overflow - // negative can be slightly bigger than positive - if (!isNegative) - { - // negative integer can be one bigger than positive - if (value == long.MinValue) return ParseResult.Overflow; - - value = -value; - } - - return ParseResult.Success; - } - -#if HAS_CUSTOM_DOUBLE_PARSE - private static class IEEE754 - { - /// - /// Exponents for both powers of 10 and 0.1 - /// - private static readonly int[] MultExp64Power10 = new int[] - { - 4, 7, 10, 14, 17, 20, 24, 27, 30, 34, 37, 40, 44, 47, 50 - }; - - /// - /// Normalized powers of 10 - /// - private static readonly ulong[] MultVal64Power10 = new ulong[] - { - 0xa000000000000000, 0xc800000000000000, 0xfa00000000000000, - 0x9c40000000000000, 0xc350000000000000, 0xf424000000000000, - 0x9896800000000000, 0xbebc200000000000, 0xee6b280000000000, - 0x9502f90000000000, 0xba43b74000000000, 0xe8d4a51000000000, - 0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000, - }; - - /// - /// Normalized powers of 0.1 - /// - private static readonly ulong[] MultVal64Power10Inv = new ulong[] - { - 0xcccccccccccccccd, 0xa3d70a3d70a3d70b, 0x83126e978d4fdf3c, - 0xd1b71758e219652e, 0xa7c5ac471b478425, 0x8637bd05af6c69b7, - 0xd6bf94d5e57a42be, 0xabcc77118461ceff, 0x89705f4136b4a599, - 0xdbe6fecebdedd5c2, 0xafebff0bcb24ab02, 0x8cbccc096f5088cf, - 0xe12e13424bb40e18, 0xb424dc35095cd813, 0x901d7cf73ab0acdc, - }; - - /// - /// Exponents for both powers of 10^16 and 0.1^16 - /// - private static readonly int[] MultExp64Power10By16 = new int[] - { - 54, 107, 160, 213, 266, 319, 373, 426, 479, 532, 585, 638, - 691, 745, 798, 851, 904, 957, 1010, 1064, 1117, - }; - - /// - /// Normalized powers of 10^16 - /// - private static readonly ulong[] MultVal64Power10By16 = new ulong[] - { - 0x8e1bc9bf04000000, 0x9dc5ada82b70b59e, 0xaf298d050e4395d6, - 0xc2781f49ffcfa6d4, 0xd7e77a8f87daf7fa, 0xefb3ab16c59b14a0, - 0x850fadc09923329c, 0x93ba47c980e98cde, 0xa402b9c5a8d3a6e6, - 0xb616a12b7fe617a8, 0xca28a291859bbf90, 0xe070f78d39275566, - 0xf92e0c3537826140, 0x8a5296ffe33cc92c, 0x9991a6f3d6bf1762, - 0xaa7eebfb9df9de8a, 0xbd49d14aa79dbc7e, 0xd226fc195c6a2f88, - 0xe950df20247c83f8, 0x81842f29f2cce373, 0x8fcac257558ee4e2, - }; - - /// - /// Normalized powers of 0.1^16 - /// - private static readonly ulong[] MultVal64Power10By16Inv = new ulong[] - { - 0xe69594bec44de160, 0xcfb11ead453994c3, 0xbb127c53b17ec165, - 0xa87fea27a539e9b3, 0x97c560ba6b0919b5, 0x88b402f7fd7553ab, - 0xf64335bcf065d3a0, 0xddd0467c64bce4c4, 0xc7caba6e7c5382ed, - 0xb3f4e093db73a0b7, 0xa21727db38cb0053, 0x91ff83775423cc29, - 0x8380dea93da4bc82, 0xece53cec4a314f00, 0xd5605fcdcf32e217, - 0xc0314325637a1978, 0xad1c8eab5ee43ba2, 0x9becce62836ac5b0, - 0x8c71dcd9ba0b495c, 0xfd00b89747823938, 0xe3e27a444d8d991a, - }; - - /// - /// Packs *10^ as 64-bit floating point value according to IEEE 754 standard - /// - /// Sign - /// Mantissa - /// Exponent - /// - /// Adoption of native function NumberToDouble() from coreclr sources, - /// see https://github.com/dotnet/coreclr/blob/master/src/classlibnative/bcltype/number.cpp#L451 - /// - public static double PackDouble(bool negative, ulong val, int scale) - { - // handle zero value - if (val == 0) - { - return negative ? -0.0 : 0.0; - } - - // normalize the mantissa - int exp = 64; - - if ((val & 0xFFFFFFFF00000000) == 0) - { - val <<= 32; - exp -= 32; - } - if ((val & 0xFFFF000000000000) == 0) - { - val <<= 16; - exp -= 16; - } - if ((val & 0xFF00000000000000) == 0) - { - val <<= 8; - exp -= 8; - } - if ((val & 0xF000000000000000) == 0) - { - val <<= 4; - exp -= 4; - } - if ((val & 0xC000000000000000) == 0) - { - val <<= 2; - exp -= 2; - } - if ((val & 0x8000000000000000) == 0) - { - val <<= 1; - exp -= 1; - } - - if (scale < 0) - { - scale = -scale; - - // check scale bounds - if (scale >= 22 * 16) - { - // underflow - return negative ? -0.0 : 0.0; - } - - // perform scaling - int index = scale & 15; - if (index != 0) - { - exp -= MultExp64Power10[index - 1] - 1; - val = Mul64Lossy(val, MultVal64Power10Inv[index - 1], ref exp); - } - - index = scale >> 4; - if (index != 0) - { - exp -= MultExp64Power10By16[index - 1] - 1; - val = Mul64Lossy(val, MultVal64Power10By16Inv[index - 1], ref exp); - } - } - else - { - // check scale bounds - if (scale >= 22 * 16) - { - // overflow - return negative ? double.NegativeInfinity : double.PositiveInfinity; - } - - // perform scaling - int index = scale & 15; - if (index != 0) - { - exp += MultExp64Power10[index - 1]; - val = Mul64Lossy(val, MultVal64Power10[index - 1], ref exp); - } - - index = scale >> 4; - if (index != 0) - { - exp += MultExp64Power10By16[index - 1]; - val = Mul64Lossy(val, MultVal64Power10By16[index - 1], ref exp); - } - } - - // round & scale down - - if ((val & (1 << 10)) != 0) - { - // IEEE round to even - ulong tmp = val + ((1UL << 10) - 1 + ((val >> 11) & 1)); - if (tmp < val) - { - // overflow - tmp = (tmp >> 1) | 0x8000000000000000; - exp++; - } - val = tmp; - } - - // return the exponent to a biased state - - exp += 0x3FE; - - // handle overflow, underflow, "Epsilon - 1/2 Epsilon", denormalized, and the normal case - - if (exp <= 0) - { - if (exp == -52 && (val >= 0x8000000000000058)) - { - // round X where {Epsilon > X >= 2.470328229206232730000000E-324} up to Epsilon (instead of down to zero) - val = 0x0000000000000001; - } - else if (exp <= -52) - { - // underflow - val = 0; - } - else - { - // denormalized value - val >>= (-exp + 12); - } - } - else if (exp >= 0x7FF) - { - // overflow - val = 0x7FF0000000000000; - } - else - { - // normal positive exponent case - val = ((ulong)exp << 52) | ((val >> 11) & 0x000FFFFFFFFFFFFF); - } - - // apply sign - - if (negative) - { - val |= 0x8000000000000000; - } - - return BitConverter.Int64BitsToDouble((long)val); - } - - private static ulong Mul64Lossy(ulong a, ulong b, ref int exp) - { - ulong a_hi = (a >> 32); - uint a_lo = (uint)a; - ulong b_hi = (b >> 32); - uint b_lo = (uint)b; - - ulong result = a_hi * b_hi; - - // save some multiplications if lo-parts aren't big enough to produce carry - // (hi-parts will be always big enough, since a and b are normalized) - - if ((b_lo & 0xFFFF0000) != 0) - { - result += (a_hi * b_lo) >> 32; - } - - if ((a_lo & 0xFFFF0000) != 0) - { - result += (a_lo * b_hi) >> 32; - } - - // normalize - if ((result & 0x8000000000000000) == 0) - { - result <<= 1; - exp--; - } - - return result; - } - } - - public static ParseResult DoubleTryParse(char[] chars, int start, int length, out double value) - { - value = 0; - - if (length == 0) - { - return ParseResult.Invalid; - } - - bool isNegative = (chars[start] == '-'); - if (isNegative) - { - // text just a negative sign - if (length == 1) - { - return ParseResult.Invalid; - } - - start++; - length--; - } - - int i = start; - int end = start + length; - int numDecimalStart = end; - int numDecimalEnd = end; - int exponent = 0; - ulong mantissa = 0UL; - int mantissaDigits = 0; - int exponentFromMantissa = 0; - for (; i < end; i++) - { - char c = chars[i]; - switch (c) - { - case '.': - if (i == start) - { - return ParseResult.Invalid; - } - if (i + 1 == end) - { - return ParseResult.Invalid; - } - - if (numDecimalStart != end) - { - // multiple decimal points - return ParseResult.Invalid; - } - - numDecimalStart = i + 1; - break; - case 'e': - case 'E': - if (i == start) - { - return ParseResult.Invalid; - } - if (i == numDecimalStart) - { - // E follows decimal point - return ParseResult.Invalid; - } - i++; - if (i == end) - { - return ParseResult.Invalid; - } - - if (numDecimalStart < end) - { - numDecimalEnd = i - 1; - } - - c = chars[i]; - bool exponentNegative = false; - switch (c) - { - case '-': - exponentNegative = true; - i++; - break; - case '+': - i++; - break; - } - - // parse 3 digit - for (; i < end; i++) - { - c = chars[i]; - if (c < '0' || c > '9') - { - return ParseResult.Invalid; - } - - int newExponent = (10 * exponent) + (c - '0'); - // stops updating exponent when overflowing - if (exponent < newExponent) - { - exponent = newExponent; - } - } - - if (exponentNegative) - { - exponent = -exponent; - } - break; - default: - if (c < '0' || c > '9') - { - return ParseResult.Invalid; - } - - if (i == start && c == '0') - { - i++; - if (i != end) - { - c = chars[i]; - if (c == '.') - { - goto case '.'; - } - if (c == 'e' || c == 'E') - { - goto case 'E'; - } - - return ParseResult.Invalid; - } - } - - if (mantissaDigits < 19) - { - mantissa = (10 * mantissa) + (ulong)(c - '0'); - if (mantissa > 0) - { - ++mantissaDigits; - } - } - else - { - ++exponentFromMantissa; - } - break; - } - } - - exponent += exponentFromMantissa; - - // correct the decimal point - exponent -= (numDecimalEnd - numDecimalStart); - - value = IEEE754.PackDouble(isNegative, mantissa, exponent); - return double.IsInfinity(value) ? ParseResult.Overflow : ParseResult.Success; - } -#endif - - public static ParseResult DecimalTryParse(char[] chars, int start, int length, out decimal value) - { - value = 0M; - const decimal decimalMaxValueHi28 = 7922816251426433759354395033M; - const ulong decimalMaxValueHi19 = 7922816251426433759UL; - const ulong decimalMaxValueLo9 = 354395033UL; - const char decimalMaxValueLo1 = '5'; - - if (length == 0) return ParseResult.Invalid; - - var isNegative = chars[start] == '-'; - if (isNegative) - { - // text just a negative sign - if (length == 1) return ParseResult.Invalid; - - start++; - length--; - } - - var i = start; - var end = start + length; - var numDecimalStart = end; - var numDecimalEnd = end; - var exponent = 0; - var hi19 = 0UL; - var lo10 = 0UL; - var mantissaDigits = 0; - var exponentFromMantissa = 0; - char? digit29 = null; - bool? storeOnly28Digits = null; - for (; i < end; i++) - { - var c = chars[i]; - switch (c) - { - case '.': - if (i == start) return ParseResult.Invalid; - - if (i + 1 == end) return ParseResult.Invalid; - - if (numDecimalStart != end) - { - // multiple decimal points - return ParseResult.Invalid; - } - - numDecimalStart = i + 1; - break; - case 'e': - case 'E': - if (i == start) return ParseResult.Invalid; - - if (i == numDecimalStart) - { - // E follows decimal point - return ParseResult.Invalid; - } - i++; - if (i == end) return ParseResult.Invalid; - - if (numDecimalStart < end) numDecimalEnd = i - 1; - - c = chars[i]; - var exponentNegative = false; - switch (c) - { - case '-': - exponentNegative = true; - i++; - break; - case '+': - i++; - break; - } - - // parse 3 digit - for (; i < end; i++) - { - c = chars[i]; - if (c < '0' || c > '9') return ParseResult.Invalid; - - var newExponent = 10 * exponent + (c - '0'); - // stops updating exponent when overflowing - if (exponent < newExponent) exponent = newExponent; - } - - if (exponentNegative) exponent = -exponent; - break; - default: - if (c < '0' || c > '9') return ParseResult.Invalid; - - if (i == start && c == '0') - { - i++; - if (i != end) - { - c = chars[i]; - if (c == '.') goto case '.'; - if (c == 'e' || c == 'E') goto case 'E'; - - return ParseResult.Invalid; - } - } - - if (mantissaDigits < 29 && (mantissaDigits != 28 || !(storeOnly28Digits - ?? (storeOnly28Digits = hi19 > decimalMaxValueHi19 || hi19 == decimalMaxValueHi19 - && (lo10 > decimalMaxValueLo9 || lo10 == decimalMaxValueLo9 && c > decimalMaxValueLo1)).GetValueOrDefault()))) - { - if (mantissaDigits < 19) - hi19 = hi19 * 10UL + (ulong)(c - '0'); - else - lo10 = lo10 * 10UL + (ulong)(c - '0'); - ++mantissaDigits; - } - else - { - if (!digit29.HasValue) digit29 = c; - ++exponentFromMantissa; - } - break; - } - } - - exponent += exponentFromMantissa; - - // correct the decimal point - exponent -= numDecimalEnd - numDecimalStart; - - if (mantissaDigits <= 19) - value = hi19; - else - value = hi19 / new decimal(1, 0, 0, false, (byte)(mantissaDigits - 19)) + lo10; - - if (exponent > 0) - { - mantissaDigits += exponent; - if (mantissaDigits > 29) return ParseResult.Overflow; - - if (mantissaDigits == 29) - { - if (exponent > 1) - { - value /= new decimal(1, 0, 0, false, (byte)(exponent - 1)); - if (value > decimalMaxValueHi28) return ParseResult.Overflow; - } - else if (value == decimalMaxValueHi28 && digit29 > decimalMaxValueLo1) return ParseResult.Overflow; - - value *= 10M; - } - else - value /= new decimal(1, 0, 0, false, (byte)exponent); - } - else - { - if (digit29 >= '5' && exponent >= -28) ++value; - if (exponent < 0) - { - if (mantissaDigits + exponent + 28 <= 0) - { - value = isNegative ? -0M : 0M; - return ParseResult.Success; - } - if (exponent >= -28) - value *= new decimal(1, 0, 0, false, (byte)-exponent); - else - { - value /= 1e28M; - value *= new decimal(1, 0, 0, false, (byte)(-exponent - 28)); - } - } - } - - if (isNegative) value = -value; - - return ParseResult.Success; - } - - public static bool TryConvertGuid(string s, out Guid g) - { - // GUID has to have format 00000000-0000-0000-0000-000000000000 -#if !HAVE_GUID_TRY_PARSE - if (s == null) throw new ArgumentNullException("s"); - - var format = new Regex("^[A-Fa-f0-9]{8}-([A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}$"); - var match = format.Match(s); - if (match.Success) - { - g = new Guid(s); - return true; - } - - g = Guid.Empty; - return false; -#else - return Guid.TryParseExact(s, "D", out g); -#endif - } - - public static bool TryHexTextToInt(char[] text, int start, int end, out int value) - { - value = 0; - - for (var i = start; i < end; i++) - { - var ch = text[i]; - int chValue; - - if (ch <= 57 && ch >= 48) - chValue = ch - 48; - else if (ch <= 70 && ch >= 65) - chValue = ch - 55; - else if (ch <= 102 && ch >= 97) - chValue = ch - 87; - else - { - value = 0; - return false; - } - - value += chValue << ((end - 1 - i) * 4); - } - - return true; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeParser.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeParser.cs deleted file mode 100644 index 5a6153085..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeParser.cs +++ /dev/null @@ -1,254 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal enum ParserTimeZone - { - Unspecified = 0, - Utc = 1, - LocalWestOfUtc = 2, - LocalEastOfUtc = 3 - } - - internal struct DateTimeParser - { - static DateTimeParser() - { - Power10 = new[] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; - - Lzyyyy = "yyyy".Length; - Lzyyyy_ = "yyyy-".Length; - Lzyyyy_MM = "yyyy-MM".Length; - Lzyyyy_MM_ = "yyyy-MM-".Length; - Lzyyyy_MM_dd = "yyyy-MM-dd".Length; - Lzyyyy_MM_ddT = "yyyy-MM-ddT".Length; - LzHH = "HH".Length; - LzHH_ = "HH:".Length; - LzHH_mm = "HH:mm".Length; - LzHH_mm_ = "HH:mm:".Length; - LzHH_mm_ss = "HH:mm:ss".Length; - Lz_ = "-".Length; - Lz_zz = "-zz".Length; - } - - public int Year; - public int Month; - public int Day; - public int Hour; - public int Minute; - public int Second; - public int Fraction; - public int ZoneHour; - public int ZoneMinute; - public ParserTimeZone Zone; - - private char[] _text; - private int _end; - - private static readonly int[] Power10; - - private static readonly int Lzyyyy; - private static readonly int Lzyyyy_; - private static readonly int Lzyyyy_MM; - private static readonly int Lzyyyy_MM_; - private static readonly int Lzyyyy_MM_dd; - private static readonly int Lzyyyy_MM_ddT; - private static readonly int LzHH; - private static readonly int LzHH_; - private static readonly int LzHH_mm; - private static readonly int LzHH_mm_; - private static readonly int LzHH_mm_ss; - private static readonly int Lz_; - private static readonly int Lz_zz; - - private const short MaxFractionDigits = 7; - - public bool Parse(char[] text, int startIndex, int length) - { - _text = text; - _end = startIndex + length; - - if (ParseDate(startIndex) && ParseChar(Lzyyyy_MM_dd + startIndex, 'T') - && ParseTimeAndZoneAndWhitespace(Lzyyyy_MM_ddT + startIndex)) return true; - - return false; - } - - private bool ParseDate(int start) => Parse4Digit(start, out Year) - && 1 <= Year - && ParseChar(start + Lzyyyy, '-') - && Parse2Digit(start + Lzyyyy_, out Month) - && 1 <= Month - && Month <= 12 - && ParseChar(start + Lzyyyy_MM, '-') - && Parse2Digit(start + Lzyyyy_MM_, out Day) - && 1 <= Day - && Day <= DateTime.DaysInMonth(Year, Month); - - private bool ParseTimeAndZoneAndWhitespace(int start) => ParseTime(ref start) && ParseZone(start); - - private bool ParseTime(ref int start) - { - if (!(Parse2Digit(start, out Hour) - && Hour <= 24 - && ParseChar(start + LzHH, ':') - && Parse2Digit(start + LzHH_, out Minute) - && Minute < 60 - && ParseChar(start + LzHH_mm, ':') - && Parse2Digit(start + LzHH_mm_, out Second) - && Second < 60 - && (Hour != 24 || Minute == 0 && Second == 0))) // hour can be 24 if minute/second is zero) - return false; - - start += LzHH_mm_ss; - if (ParseChar(start, '.')) - { - Fraction = 0; - var numberOfDigits = 0; - - while (++start < _end && numberOfDigits < MaxFractionDigits) - { - var digit = _text[start] - '0'; - if (digit < 0 || digit > 9) break; - - Fraction = Fraction * 10 + digit; - - numberOfDigits++; - } - - if (numberOfDigits < MaxFractionDigits) - { - if (numberOfDigits == 0) return false; - - Fraction *= Power10[MaxFractionDigits - numberOfDigits]; - } - - if (Hour == 24 && Fraction != 0) return false; - } - return true; - } - - private bool ParseZone(int start) - { - if (start < _end) - { - var ch = _text[start]; - if (ch == 'Z' || ch == 'z') - { - Zone = ParserTimeZone.Utc; - start++; - } - else - { - if (start + 2 < _end - && Parse2Digit(start + Lz_, out ZoneHour) - && ZoneHour <= 99) - { - switch (ch) - { - case '-': - Zone = ParserTimeZone.LocalWestOfUtc; - start += Lz_zz; - break; - - case '+': - Zone = ParserTimeZone.LocalEastOfUtc; - start += Lz_zz; - break; - } - } - - if (start < _end) - { - if (ParseChar(start, ':')) - { - start += 1; - - if (start + 1 < _end - && Parse2Digit(start, out ZoneMinute) - && ZoneMinute <= 99) - start += 2; - } - else - { - if (start + 1 < _end - && Parse2Digit(start, out ZoneMinute) - && ZoneMinute <= 99) - start += 2; - } - } - } - } - - return start == _end; - } - - private bool Parse4Digit(int start, out int num) - { - if (start + 3 < _end) - { - var digit1 = _text[start] - '0'; - var digit2 = _text[start + 1] - '0'; - var digit3 = _text[start + 2] - '0'; - var digit4 = _text[start + 3] - '0'; - if (0 <= digit1 && digit1 < 10 - && 0 <= digit2 && digit2 < 10 - && 0 <= digit3 && digit3 < 10 - && 0 <= digit4 && digit4 < 10) - { - num = ((digit1 * 10 + digit2) * 10 + digit3) * 10 + digit4; - return true; - } - } - num = 0; - return false; - } - - private bool Parse2Digit(int start, out int num) - { - if (start + 1 < _end) - { - var digit1 = _text[start] - '0'; - var digit2 = _text[start + 1] - '0'; - if (0 <= digit1 && digit1 < 10 - && 0 <= digit2 && digit2 < 10) - { - num = digit1 * 10 + digit2; - return true; - } - } - num = 0; - return false; - } - - private bool ParseChar(int start, char ch) => start < _end && _text[start] == ch; - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeUtils.cs deleted file mode 100644 index c2398a32f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DateTimeUtils.cs +++ /dev/null @@ -1,774 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.IO; -using System.Xml; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class DateTimeUtils - { - internal static readonly long InitialJavaScriptDateTicks = 621355968000000000; - private const string IsoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK"; - - private const int DaysPer100Years = 36524; - private const int DaysPer400Years = 146097; - private const int DaysPer4Years = 1461; - private const int DaysPerYear = 365; - private const long TicksPerDay = 864000000000L; - private static readonly int[] DaysToMonth365; - private static readonly int[] DaysToMonth366; - - static DateTimeUtils() - { - DaysToMonth365 = new[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - DaysToMonth366 = new[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; - } - - public static TimeSpan GetUtcOffset(this DateTime d) => TimeZoneInfo.Local.GetUtcOffset(d); - -#if !(PORTABLE40 || PORTABLE) || NETSTANDARD1_3 - public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind) - { - switch (kind) - { - case DateTimeKind.Local: - return XmlDateTimeSerializationMode.Local; - case DateTimeKind.Unspecified: - return XmlDateTimeSerializationMode.Unspecified; - case DateTimeKind.Utc: - return XmlDateTimeSerializationMode.Utc; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(kind), kind, "Unexpected DateTimeKind value."); - } - } -#else - public static string ToDateTimeFormat(DateTimeKind kind) - { - switch (kind) - { - case DateTimeKind.Local: - return IsoDateFormat; - case DateTimeKind.Unspecified: - return "yyyy-MM-ddTHH:mm:ss.FFFFFFF"; - case DateTimeKind.Utc: - return "yyyy-MM-ddTHH:mm:ss.FFFFFFFZ"; - default: - throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(kind), kind, "Unexpected DateTimeKind value."); - } - } -#endif - - internal static DateTime EnsureDateTime(DateTime value, DateTimeZoneHandling timeZone) - { - switch (timeZone) - { - case DateTimeZoneHandling.Local: - value = SwitchToLocalTime(value); - break; - case DateTimeZoneHandling.Utc: - value = SwitchToUtcTime(value); - break; - case DateTimeZoneHandling.Unspecified: - value = new DateTime(value.Ticks, DateTimeKind.Unspecified); - break; - case DateTimeZoneHandling.RoundtripKind: - break; - default: - throw new ArgumentException("Invalid date time handling value."); - } - - return value; - } - - private static DateTime SwitchToLocalTime(DateTime value) - { - switch (value.Kind) - { - case DateTimeKind.Unspecified: - return new DateTime(value.Ticks, DateTimeKind.Local); - - case DateTimeKind.Utc: - return value.ToLocalTime(); - - case DateTimeKind.Local: - return value; - } - return value; - } - - private static DateTime SwitchToUtcTime(DateTime value) - { - switch (value.Kind) - { - case DateTimeKind.Unspecified: - return new DateTime(value.Ticks, DateTimeKind.Utc); - - case DateTimeKind.Utc: - return value; - - case DateTimeKind.Local: - return value.ToUniversalTime(); - } - return value; - } - - private static long ToUniversalTicks(DateTime dateTime) - { - if (dateTime.Kind == DateTimeKind.Utc) return dateTime.Ticks; - - return ToUniversalTicks(dateTime, dateTime.GetUtcOffset()); - } - - private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset) - { - // special case min and max value - // they never have a timezone appended to avoid issues - if (dateTime.Kind == DateTimeKind.Utc || dateTime == DateTime.MaxValue || dateTime == DateTime.MinValue) return dateTime.Ticks; - - var ticks = dateTime.Ticks - offset.Ticks; - if (ticks > 3155378975999999999L) return 3155378975999999999L; - - if (ticks < 0L) return 0L; - - return ticks; - } - - internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset) - { - var universalTicks = ToUniversalTicks(dateTime, offset); - - return UniversalTicksToJavaScriptTicks(universalTicks); - } - - internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime) => ConvertDateTimeToJavaScriptTicks(dateTime, true); - - internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc) - { - var ticks = convertToUtc ? ToUniversalTicks(dateTime) : dateTime.Ticks; - - return UniversalTicksToJavaScriptTicks(ticks); - } - - private static long UniversalTicksToJavaScriptTicks(long universalTicks) - { - var javaScriptTicks = (universalTicks - InitialJavaScriptDateTicks) / 10000; - - return javaScriptTicks; - } - - internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks) - { - var dateTime = new DateTime(javaScriptTicks * 10000 + InitialJavaScriptDateTicks, DateTimeKind.Utc); - - return dateTime; - } - - #region Parse - - internal static bool TryParseDateTimeIso(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) - { - var dateTimeParser = new DateTimeParser(); - if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) - { - dt = default; - return false; - } - - var d = CreateDateTime(dateTimeParser); - - long ticks; - - switch (dateTimeParser.Zone) - { - case ParserTimeZone.Utc: - d = new DateTime(d.Ticks, DateTimeKind.Utc); - break; - - case ParserTimeZone.LocalWestOfUtc: - { - var offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); - ticks = d.Ticks + offset.Ticks; - if (ticks <= DateTime.MaxValue.Ticks) - d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime(); - else - { - ticks += d.GetUtcOffset().Ticks; - if (ticks > DateTime.MaxValue.Ticks) ticks = DateTime.MaxValue.Ticks; - - d = new DateTime(ticks, DateTimeKind.Local); - } - break; - } - case ParserTimeZone.LocalEastOfUtc: - { - var offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); - ticks = d.Ticks - offset.Ticks; - if (ticks >= DateTime.MinValue.Ticks) - d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime(); - else - { - ticks += d.GetUtcOffset().Ticks; - if (ticks < DateTime.MinValue.Ticks) ticks = DateTime.MinValue.Ticks; - - d = new DateTime(ticks, DateTimeKind.Local); - } - break; - } - } - - dt = EnsureDateTime(d, dateTimeZoneHandling); - return true; - } - -#if HAVE_DATE_TIME_OFFSET - internal static bool TryParseDateTimeOffsetIso(StringReference text, out DateTimeOffset dt) - { - DateTimeParser dateTimeParser = new DateTimeParser(); - if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) - { - dt = default; - return false; - } - - DateTime d = CreateDateTime(dateTimeParser); - - TimeSpan offset; - - switch (dateTimeParser.Zone) - { - case ParserTimeZone.Utc: - offset = new TimeSpan(0L); - break; - case ParserTimeZone.LocalWestOfUtc: - offset = new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0); - break; - case ParserTimeZone.LocalEastOfUtc: - offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); - break; - default: - offset = TimeZoneInfo.Local.GetUtcOffset(d); - break; - } - - long ticks = d.Ticks - offset.Ticks; - if (ticks < 0 || ticks > 3155378975999999999) - { - dt = default; - return false; - } - - dt = new DateTimeOffset(d, offset); - return true; - } -#endif - - private static DateTime CreateDateTime(DateTimeParser dateTimeParser) - { - bool is24Hour; - if (dateTimeParser.Hour == 24) - { - is24Hour = true; - dateTimeParser.Hour = 0; - } - else - is24Hour = false; - - var d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, - dateTimeParser.Second); - d = d.AddTicks(dateTimeParser.Fraction); - - if (is24Hour) d = d.AddDays(1); - return d; - } - - internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, - CultureInfo culture, out DateTime dt - ) - { - if (s.Length > 0) - { - var i = s.StartIndex; - if (s[i] == '/') - { - if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/")) - { - if (TryParseDateTimeMicrosoft(s, dateTimeZoneHandling, out dt)) - return true; - } - } - else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[i]) && s[i + 10] == 'T') - { - if (TryParseDateTimeIso(s, dateTimeZoneHandling, out dt)) - return true; - } - - if (!StringUtils.IsNullOrEmpty(dateFormatString)) - { - if (TryParseDateTimeExact(s.ToString(), dateTimeZoneHandling, dateFormatString, culture, out dt)) - return true; - } - } - - dt = default; - return false; - } - - internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, - out DateTime dt - ) - { - if (s.Length > 0) - { - if (s[0] == '/') - { - if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal)) - { - if (TryParseDateTimeMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), dateTimeZoneHandling, out dt)) - return true; - } - } - else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T') - { - if (DateTime.TryParseExact(s, IsoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt)) - { - dt = EnsureDateTime(dt, dateTimeZoneHandling); - return true; - } - } - - if (!StringUtils.IsNullOrEmpty(dateFormatString)) - { - if (TryParseDateTimeExact(s, dateTimeZoneHandling, dateFormatString, culture, out dt)) - return true; - } - } - - dt = default; - return false; - } - -#if HAVE_DATE_TIME_OFFSET - internal static bool TryParseDateTimeOffset(StringReference s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) - { - if (s.Length > 0) - { - int i = s.StartIndex; - if (s[i] == '/') - { - if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/")) - { - if (TryParseDateTimeOffsetMicrosoft(s, out dt)) - { - return true; - } - } - } - else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[i]) && s[i + 10] == 'T') - { - if (TryParseDateTimeOffsetIso(s, out dt)) - { - return true; - } - } - - if (!StringUtils.IsNullOrEmpty(dateFormatString)) - { - if (TryParseDateTimeOffsetExact(s.ToString(), dateFormatString, culture, out dt)) - { - return true; - } - } - } - - dt = default; - return false; - } - - internal static bool TryParseDateTimeOffset(string s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) - { - if (s.Length > 0) - { - if (s[0] == '/') - { - if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal)) - { - if (TryParseDateTimeOffsetMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) - { - return true; - } - } - } - else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T') - { - if (DateTimeOffset.TryParseExact(s, IsoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt)) - { - if (TryParseDateTimeOffsetIso(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) - { - return true; - } - } - } - - if (!StringUtils.IsNullOrEmpty(dateFormatString)) - { - if (TryParseDateTimeOffsetExact(s, dateFormatString, culture, out dt)) - { - return true; - } - } - } - - dt = default; - return false; - } -#endif - - private static bool TryParseMicrosoftDate(StringReference text, out long ticks, out TimeSpan offset, out DateTimeKind kind) - { - kind = DateTimeKind.Utc; - - var index = text.IndexOf('+', 7, text.Length - 8); - - if (index == -1) index = text.IndexOf('-', 7, text.Length - 8); - - if (index != -1) - { - kind = DateTimeKind.Local; - - if (!TryReadOffset(text, index + text.StartIndex, out offset)) - { - ticks = 0; - return false; - } - } - else - { - offset = TimeSpan.Zero; - index = text.Length - 2; - } - - return ConvertUtils.Int64TryParse(text.Chars, 6 + text.StartIndex, index - 6, out ticks) == ParseResult.Success; - } - - private static bool TryParseDateTimeMicrosoft(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) - { - if (!TryParseMicrosoftDate(text, out var ticks, out _, out var kind)) - { - dt = default; - return false; - } - - var utcDateTime = ConvertJavaScriptTicksToDateTime(ticks); - - switch (kind) - { - case DateTimeKind.Unspecified: - dt = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified); - break; - case DateTimeKind.Local: - dt = utcDateTime.ToLocalTime(); - break; - default: - dt = utcDateTime; - break; - } - - dt = EnsureDateTime(dt, dateTimeZoneHandling); - return true; - } - - private static bool TryParseDateTimeExact(string text, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, - CultureInfo culture, out DateTime dt - ) - { - if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out var temp)) - { - temp = EnsureDateTime(temp, dateTimeZoneHandling); - dt = temp; - return true; - } - - dt = default; - return false; - } - -#if HAVE_DATE_TIME_OFFSET - private static bool TryParseDateTimeOffsetMicrosoft(StringReference text, out DateTimeOffset dt) - { - if (!TryParseMicrosoftDate(text, out long ticks, out TimeSpan offset, out _)) - { - dt = default(DateTime); - return false; - } - - DateTime utcDateTime = ConvertJavaScriptTicksToDateTime(ticks); - - dt = new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset); - return true; - } - - private static bool TryParseDateTimeOffsetExact(string text, string dateFormatString, CultureInfo culture, out DateTimeOffset dt) - { - if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out DateTimeOffset temp)) - { - dt = temp; - return true; - } - - dt = default; - return false; - } -#endif - - private static bool TryReadOffset(StringReference offsetText, int startIndex, out TimeSpan offset) - { - var negative = offsetText[startIndex] == '-'; - - if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 1, 2, out var hours) != ParseResult.Success) - { - offset = default; - return false; - } - - var minutes = 0; - if (offsetText.Length - startIndex > 5) - { - if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 3, 2, out minutes) != ParseResult.Success) - { - offset = default; - return false; - } - } - - offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes); - if (negative) offset = offset.Negate(); - - return true; - } - - #endregion - - #region Write - - internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string? formatString, - CultureInfo culture - ) - { - if (StringUtils.IsNullOrEmpty(formatString)) - { - var chars = new char[64]; - var pos = WriteDateTimeString(chars, 0, value, null, value.Kind, format); - writer.Write(chars, 0, pos); - } - else - writer.Write(value.ToString(formatString, culture)); - } - - internal static int WriteDateTimeString(char[] chars, int start, DateTime value, TimeSpan? offset, DateTimeKind kind, - DateFormatHandling format - ) - { - var pos = start; - - if (format == DateFormatHandling.MicrosoftDateFormat) - { - var o = offset ?? value.GetUtcOffset(); - - var javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value, o); - - @"\/Date(".CopyTo(0, chars, pos, 7); - pos += 7; - - var ticksText = javaScriptTicks.ToString(CultureInfo.InvariantCulture); - ticksText.CopyTo(0, chars, pos, ticksText.Length); - pos += ticksText.Length; - - switch (kind) - { - case DateTimeKind.Unspecified: - if (value != DateTime.MaxValue && value != DateTime.MinValue) pos = WriteDateTimeOffset(chars, pos, o, format); - break; - case DateTimeKind.Local: - pos = WriteDateTimeOffset(chars, pos, o, format); - break; - } - - @")\/".CopyTo(0, chars, pos, 3); - pos += 3; - } - else - { - pos = WriteDefaultIsoDate(chars, pos, value); - - switch (kind) - { - case DateTimeKind.Local: - pos = WriteDateTimeOffset(chars, pos, offset ?? value.GetUtcOffset(), format); - break; - case DateTimeKind.Utc: - chars[pos++] = 'Z'; - break; - } - } - - return pos; - } - - internal static int WriteDefaultIsoDate(char[] chars, int start, DateTime dt) - { - var length = 19; - - GetDateValues(dt, out var year, out var month, out var day); - - CopyIntToCharArray(chars, start, year, 4); - chars[start + 4] = '-'; - CopyIntToCharArray(chars, start + 5, month, 2); - chars[start + 7] = '-'; - CopyIntToCharArray(chars, start + 8, day, 2); - chars[start + 10] = 'T'; - CopyIntToCharArray(chars, start + 11, dt.Hour, 2); - chars[start + 13] = ':'; - CopyIntToCharArray(chars, start + 14, dt.Minute, 2); - chars[start + 16] = ':'; - CopyIntToCharArray(chars, start + 17, dt.Second, 2); - - var fraction = (int)(dt.Ticks % 10000000L); - - if (fraction != 0) - { - var digits = 7; - while (fraction % 10 == 0) - { - digits--; - fraction /= 10; - } - - chars[start + 19] = '.'; - CopyIntToCharArray(chars, start + 20, fraction, digits); - - length += digits + 1; - } - - return start + length; - } - - private static void CopyIntToCharArray(char[] chars, int start, int value, int digits) - { - while (digits-- != 0) - { - chars[start + digits] = (char)(value % 10 + 48); - value /= 10; - } - } - - internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset, DateFormatHandling format) - { - chars[start++] = offset.Ticks >= 0L ? '+' : '-'; - - var absHours = Math.Abs(offset.Hours); - CopyIntToCharArray(chars, start, absHours, 2); - start += 2; - - if (format == DateFormatHandling.IsoDateFormat) chars[start++] = ':'; - - var absMinutes = Math.Abs(offset.Minutes); - CopyIntToCharArray(chars, start, absMinutes, 2); - start += 2; - - return start; - } - -#if HAVE_DATE_TIME_OFFSET - internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string? formatString, CultureInfo culture) - { - if (StringUtils.IsNullOrEmpty(formatString)) - { - char[] chars = new char[64]; - int pos = - WriteDateTimeString(chars, 0, (format == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, format); - - writer.Write(chars, 0, pos); - } - else - { - writer.Write(value.ToString(formatString, culture)); - } - } -#endif - - #endregion - - private static void GetDateValues(DateTime td, out int year, out int month, out int day) - { - var ticks = td.Ticks; - // n = number of days since 1/1/0001 - var n = (int)(ticks / TicksPerDay); - // y400 = number of whole 400-year periods since 1/1/0001 - var y400 = n / DaysPer400Years; - // n = day number within 400-year period - n -= y400 * DaysPer400Years; - // y100 = number of whole 100-year periods within 400-year period - var y100 = n / DaysPer100Years; - // Last 100-year period has an extra day, so decrement result if 4 - if (y100 == 4) y100 = 3; - // n = day number within 100-year period - n -= y100 * DaysPer100Years; - // y4 = number of whole 4-year periods within 100-year period - var y4 = n / DaysPer4Years; - // n = day number within 4-year period - n -= y4 * DaysPer4Years; - // y1 = number of whole years within 4-year period - var y1 = n / DaysPerYear; - // Last year has an extra day, so decrement result if 4 - if (y1 == 4) y1 = 3; - - year = y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1; - - // n = day number within year - n -= y1 * DaysPerYear; - - // Leap year calculation looks different from IsLeapYear since y1, y4, - // and y100 are relative to year 1, not year 0 - var leapYear = y1 == 3 && (y4 != 24 || y100 == 3); - var days = leapYear ? DaysToMonth366 : DaysToMonth365; - // All months have less than 32 days, so n >> 5 is a good conservative - // estimate for the month - var m = n >> (5 + 1); - // m = 1-based month number - while (n >= days[m]) m++; - - month = m; - - // Return 1-based day-of-month - day = n - days[m - 1] + 1; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DictionaryWrapper.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DictionaryWrapper.cs deleted file mode 100644 index 1d452d821..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DictionaryWrapper.cs +++ /dev/null @@ -1,593 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal interface IWrappedDictionary - : IDictionary - { - object UnderlyingDictionary { get; } - } - - internal class DictionaryWrapper : IDictionary, IWrappedDictionary - { - private readonly IDictionary? _dictionary; - private readonly IDictionary? _genericDictionary; -#if HAVE_READ_ONLY_COLLECTIONS - private readonly IReadOnlyDictionary? _readOnlyDictionary; -#endif - private object? _syncRoot; - - public DictionaryWrapper(IDictionary dictionary) - { - ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary)); - - _dictionary = dictionary; - } - - public DictionaryWrapper(IDictionary dictionary) - { - ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary)); - - _genericDictionary = dictionary; - } - -#if HAVE_READ_ONLY_COLLECTIONS - public DictionaryWrapper(IReadOnlyDictionary dictionary) - { - ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary)); - - _readOnlyDictionary = dictionary; - } -#endif - - internal IDictionary GenericDictionary - { - get - { - MiscellaneousUtils.Assert(_genericDictionary != null); - return _genericDictionary; - } - } - - public void Add(TKey key, TValue value) - { - if (_dictionary != null) - _dictionary.Add(key, value); - else if (_genericDictionary != null) - _genericDictionary.Add(key, value); - else - throw new NotSupportedException(); - } - - public bool ContainsKey(TKey key) - { - if (_dictionary != null) - return _dictionary.Contains(key); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.ContainsKey(key); - } -#endif - - return GenericDictionary.ContainsKey(key); - } - - public ICollection Keys - { - get - { - if (_dictionary != null) - return _dictionary.Keys.Cast().ToList(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Keys.ToList(); - } -#endif - - return GenericDictionary.Keys; - } - } - - public bool Remove(TKey key) - { - if (_dictionary != null) - { - if (_dictionary.Contains(key)) - { - _dictionary.Remove(key); - return true; - } - return false; - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - return GenericDictionary.Remove(key); - } - -#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). - public bool TryGetValue(TKey key, out TValue? value) -#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). - { - if (_dictionary != null) - { - if (!_dictionary.Contains(key)) - { -#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. - value = default; -#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. - return false; - } - value = (TValue)_dictionary[key]; - return true; - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - return GenericDictionary.TryGetValue(key, out value); - } - - public ICollection Values - { - get - { - if (_dictionary != null) - return _dictionary.Values.Cast().ToList(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Values.ToList(); - } -#endif - - return GenericDictionary.Values; - } - } - - public TValue this[TKey key] - { - get - { - if (_dictionary != null) - return (TValue)_dictionary[key]; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary[key]; - } -#endif - - return GenericDictionary[key]; - } - set - { - if (_dictionary != null) - _dictionary[key] = value; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary[key] = value; - } - } - - public void Add(KeyValuePair item) - { - if (_dictionary != null) - ((IList)_dictionary).Add(item); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - _genericDictionary?.Add(item); - } - - public void Clear() - { - if (_dictionary != null) - _dictionary.Clear(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary.Clear(); - } - - public bool Contains(KeyValuePair item) - { - if (_dictionary != null) - return ((IList)_dictionary).Contains(item); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Contains(item); - } -#endif - - return GenericDictionary.Contains(item); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (_dictionary != null) - { - // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations. - var e = _dictionary.GetEnumerator(); - try - { - while (e.MoveNext()) - { - var entry = e.Entry; - array[arrayIndex++] = new KeyValuePair((TKey)entry.Key, (TValue)entry.Value); - } - } - finally - { - (e as IDisposable)?.Dispose(); - } - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary.CopyTo(array, arrayIndex); - } - - public int Count - { - get - { - if (_dictionary != null) - return _dictionary.Count; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Count; - } -#endif - - return GenericDictionary.Count; - } - } - - public bool IsReadOnly - { - get - { - if (_dictionary != null) - return _dictionary.IsReadOnly; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return true; - } -#endif - - return GenericDictionary.IsReadOnly; - } - } - - public bool Remove(KeyValuePair item) - { - if (_dictionary != null) - { - if (_dictionary.Contains(item.Key)) - { - var value = _dictionary[item.Key]; - - if (Equals(value, item.Value)) - { - _dictionary.Remove(item.Key); - return true; - } - return false; - } - return true; - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - return GenericDictionary.Remove(item); - } - - public IEnumerator> GetEnumerator() - { - if (_dictionary != null) - { - return _dictionary.Cast() - .Select(de => new KeyValuePair((TKey)de.Key, (TValue)de.Value)) - .GetEnumerator(); - } -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.GetEnumerator(); - } -#endif - - return GenericDictionary.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - void IDictionary.Add(object key, object value) - { - if (_dictionary != null) - _dictionary.Add(key, value); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary.Add((TKey)key, (TValue)value); - } - - object? IDictionary.this[object key] - { - get - { - if (_dictionary != null) - return _dictionary[key]; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary[(TKey)key]; - } -#endif - - return GenericDictionary[(TKey)key]; - } - set - { - if (_dictionary != null) - _dictionary[key] = value; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - { - // Consider changing this code to call GenericDictionary.Remove when value is null. - // -#pragma warning disable CS8601 // Possible null reference assignment. -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - GenericDictionary[(TKey)key] = (TValue)value; -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. -#pragma warning restore CS8601 // Possible null reference assignment. - } - } - } - - private readonly struct DictionaryEnumerator : IDictionaryEnumerator - { - private readonly IEnumerator> _e; - - public DictionaryEnumerator(IEnumerator> e) - { - ValidationUtils.ArgumentNotNull(e, nameof(e)); - _e = e; - } - - public DictionaryEntry Entry => (DictionaryEntry)Current; - - public object Key => Entry.Key; - - public object Value => Entry.Value; - - public object Current => new DictionaryEntry(_e.Current.Key, _e.Current.Value); - - public bool MoveNext() => _e.MoveNext(); - - public void Reset() => _e.Reset(); - } - - IDictionaryEnumerator IDictionary.GetEnumerator() - { - if (_dictionary != null) - return _dictionary.GetEnumerator(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return new DictionaryEnumerator(_readOnlyDictionary.GetEnumerator()); - } -#endif - - return new DictionaryEnumerator(GenericDictionary.GetEnumerator()); - } - - bool IDictionary.Contains(object key) - { - if (_genericDictionary != null) - return _genericDictionary.ContainsKey((TKey)key); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.ContainsKey((TKey)key); - } -#endif - - return _dictionary!.Contains(key); - } - - bool IDictionary.IsFixedSize - { - get - { - if (_genericDictionary != null) - return false; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return true; - } -#endif - - return _dictionary!.IsFixedSize; - } - } - - ICollection IDictionary.Keys - { - get - { - if (_genericDictionary != null) - return _genericDictionary.Keys.ToList(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Keys.ToList(); - } -#endif - - return _dictionary!.Keys; - } - } - - public void Remove(object key) - { - if (_dictionary != null) - _dictionary.Remove(key); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary.Remove((TKey)key); - } - - ICollection IDictionary.Values - { - get - { - if (_genericDictionary != null) - return _genericDictionary.Values.ToList(); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary.Values.ToList(); - } -#endif - - return _dictionary!.Values; - } - } - - void ICollection.CopyTo(Array array, int index) - { - if (_dictionary != null) - _dictionary.CopyTo(array, index); -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - throw new NotSupportedException(); - } -#endif - else - GenericDictionary.CopyTo((KeyValuePair[])array, index); - } - - bool ICollection.IsSynchronized - { - get - { - if (_dictionary != null) - return _dictionary.IsSynchronized; - - return false; - } - } - - object ICollection.SyncRoot - { - get - { - if (_syncRoot == null) Interlocked.CompareExchange(ref _syncRoot, new object(), null); - - return _syncRoot; - } - } - - public object UnderlyingDictionary - { - get - { - if (_dictionary != null) - return _dictionary; -#if HAVE_READ_ONLY_COLLECTIONS - else if (_readOnlyDictionary != null) - { - return _readOnlyDictionary; - } -#endif - - return GenericDictionary; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxy.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxy.cs deleted file mode 100644 index 721c29712..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxy.cs +++ /dev/null @@ -1,112 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System.Collections.Generic; -using System.Dynamic; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class DynamicProxy - { - public virtual IEnumerable GetDynamicMemberNames(T instance) - { - return CollectionUtils.ArrayEmpty(); - } - - public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object? result) - { - result = null; - return false; - } - - public virtual bool TryConvert(T instance, ConvertBinder binder, out object? result) - { - result = null; - return false; - } - - public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object? result) - { - result = null; - return false; - } - - public virtual bool TryDeleteIndex(T instance, DeleteIndexBinder binder, object[] indexes) - { - return false; - } - - public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder) - { - return false; - } - - public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object? result) - { - result = null; - return false; - } - - public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object? result) - { - result = null; - return false; - } - - public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object? result) - { - result = null; - return false; - } - - public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object? result) - { - result = null; - return false; - } - - public virtual bool TrySetIndex(T instance, SetIndexBinder binder, object[] indexes, object value) - { - return false; - } - - public virtual bool TrySetMember(T instance, SetMemberBinder binder, object value) - { - return false; - } - - public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object? result) - { - result = null; - return false; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs deleted file mode 100644 index 0ce875711..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs +++ /dev/null @@ -1,395 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Linq; -using System.Linq.Expressions; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal sealed class DynamicProxyMetaObject : DynamicMetaObject - { - private readonly DynamicProxy _proxy; - - internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy proxy) - : base(expression, BindingRestrictions.Empty, value) - { - _proxy = proxy; - } - - private bool IsOverridden(string method) - { - return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof(DynamicProxy), method); - } - - public override DynamicMetaObject BindGetMember(GetMemberBinder binder) - { - return IsOverridden(nameof(DynamicProxy.TryGetMember)) - ? CallMethodWithResult(nameof(DynamicProxy.TryGetMember), binder, NoArgs, e => binder.FallbackGetMember(this, e)) - : base.BindGetMember(binder); - } - - public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) - { - return IsOverridden(nameof(DynamicProxy.TrySetMember)) - ? CallMethodReturnLast(nameof(DynamicProxy.TrySetMember), binder, GetArgs(value), e => binder.FallbackSetMember(this, value, e)) - : base.BindSetMember(binder, value); - } - - public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) - { - return IsOverridden(nameof(DynamicProxy.TryDeleteMember)) - ? CallMethodNoResult(nameof(DynamicProxy.TryDeleteMember), binder, NoArgs, e => binder.FallbackDeleteMember(this, e)) - : base.BindDeleteMember(binder); - } - - public override DynamicMetaObject BindConvert(ConvertBinder binder) - { - return IsOverridden(nameof(DynamicProxy.TryConvert)) - ? CallMethodWithResult(nameof(DynamicProxy.TryConvert), binder, NoArgs, e => binder.FallbackConvert(this, e)) - : base.BindConvert(binder); - } - - public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) - { - if (!IsOverridden(nameof(DynamicProxy.TryInvokeMember))) - { - return base.BindInvokeMember(binder, args); - } - - // - // Generate a tree like: - // - // { - // object result; - // TryInvokeMember(payload, out result) - // ? result - // : TryGetMember(payload, out result) - // ? FallbackInvoke(result) - // : fallbackResult - // } - // - // Then it calls FallbackInvokeMember with this tree as the - // "error", giving the language the option of using this - // tree or doing .NET binding. - // - Fallback fallback = e => binder.FallbackInvokeMember(this, args, e); - - return BuildCallMethodWithResult( - nameof(DynamicProxy.TryInvokeMember), - binder, - GetArgArray(args), - BuildCallMethodWithResult( - nameof(DynamicProxy.TryGetMember), - new GetBinderAdapter(binder), - NoArgs, - fallback(null), - e => binder.FallbackInvoke(e, args, null) - ), - null - ); - } - - public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) - { - return IsOverridden(nameof(DynamicProxy.TryCreateInstance)) - ? CallMethodWithResult(nameof(DynamicProxy.TryCreateInstance), binder, GetArgArray(args), e => binder.FallbackCreateInstance(this, args, e)) - : base.BindCreateInstance(binder, args); - } - - public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) - { - return IsOverridden(nameof(DynamicProxy.TryInvoke)) - ? CallMethodWithResult(nameof(DynamicProxy.TryInvoke), binder, GetArgArray(args), e => binder.FallbackInvoke(this, args, e)) - : base.BindInvoke(binder, args); - } - - public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) - { - return IsOverridden(nameof(DynamicProxy.TryBinaryOperation)) - ? CallMethodWithResult(nameof(DynamicProxy.TryBinaryOperation), binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e)) - : base.BindBinaryOperation(binder, arg); - } - - public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) - { - return IsOverridden(nameof(DynamicProxy.TryUnaryOperation)) - ? CallMethodWithResult(nameof(DynamicProxy.TryUnaryOperation), binder, NoArgs, e => binder.FallbackUnaryOperation(this, e)) - : base.BindUnaryOperation(binder); - } - - public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) - { - return IsOverridden(nameof(DynamicProxy.TryGetIndex)) - ? CallMethodWithResult(nameof(DynamicProxy.TryGetIndex), binder, GetArgArray(indexes), e => binder.FallbackGetIndex(this, indexes, e)) - : base.BindGetIndex(binder, indexes); - } - - public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) - { - return IsOverridden(nameof(DynamicProxy.TrySetIndex)) - ? CallMethodReturnLast(nameof(DynamicProxy.TrySetIndex), binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e)) - : base.BindSetIndex(binder, indexes, value); - } - - public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) - { - return IsOverridden(nameof(DynamicProxy.TryDeleteIndex)) - ? CallMethodNoResult(nameof(DynamicProxy.TryDeleteIndex), binder, GetArgArray(indexes), e => binder.FallbackDeleteIndex(this, indexes, e)) - : base.BindDeleteIndex(binder, indexes); - } - - private delegate DynamicMetaObject Fallback(DynamicMetaObject? errorSuggestion); - - private static Expression[] NoArgs => CollectionUtils.ArrayEmpty(); - - private static IEnumerable GetArgs(params DynamicMetaObject[] args) - { - return args.Select(arg => - { - Expression exp = arg.Expression; - return exp.Type.IsValueType() ? Expression.Convert(exp, typeof(object)) : exp; - }); - } - - private static Expression[] GetArgArray(DynamicMetaObject[] args) - { - return new[] { Expression.NewArrayInit(typeof(object), GetArgs(args)) }; - } - - private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value) - { - Expression exp = value.Expression; - return new[] - { - Expression.NewArrayInit(typeof(object), GetArgs(args)), - exp.Type.IsValueType() ? Expression.Convert(exp, typeof(object)) : exp - }; - } - - private static ConstantExpression Constant(DynamicMetaObjectBinder binder) - { - Type t = binder.GetType(); - while (!t.IsVisible()) - { - t = t.BaseType(); - } - return Expression.Constant(binder, t); - } - - /// - /// Helper method for generating a MetaObject which calls a - /// specific method on Dynamic that returns a result - /// - private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback, Fallback? fallbackInvoke - = null) - { - // - // First, call fallback to do default binding - // This produces either an error or a call to a .NET member - // - DynamicMetaObject fallbackResult = fallback(null); - - return BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke); - } - - private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, DynamicMetaObject fallbackResult, Fallback? fallbackInvoke) - { - // - // Build a new expression like: - // { - // object result; - // TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult - // } - // - ParameterExpression result = Expression.Parameter(typeof(object), null); - - IList callArgs = new List(); - callArgs.Add(Expression.Convert(Expression, typeof(T))); - callArgs.Add(Constant(binder)); - callArgs.AddRange(args); - callArgs.Add(result); - - DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty); - - // Need to add a conversion if calling TryConvert - if (binder.ReturnType != typeof(object)) - { - UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType); - // will always be a cast or unbox - - resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions); - } - - if (fallbackInvoke != null) - { - resultMetaObject = fallbackInvoke(resultMetaObject); - } - - DynamicMetaObject callDynamic = new DynamicMetaObject( - Expression.Block( - new[] { result }, - Expression.Condition( - Expression.Call( - Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), - callArgs - ), - resultMetaObject.Expression, - fallbackResult.Expression, - binder.ReturnType - ) - ), - GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions) - ); - - return callDynamic; - } - - /// - /// Helper method for generating a MetaObject which calls a - /// specific method on Dynamic, but uses one of the arguments for - /// the result. - /// - private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback) - { - // - // First, call fallback to do default binding - // This produces either an error or a call to a .NET member - // - DynamicMetaObject fallbackResult = fallback(null); - - // - // Build a new expression like: - // { - // object result; - // TrySetMember(payload, result = value) ? result : fallbackResult - // } - // - ParameterExpression result = Expression.Parameter(typeof(object), null); - - IList callArgs = new List(); - callArgs.Add(Expression.Convert(Expression, typeof(T))); - callArgs.Add(Constant(binder)); - callArgs.AddRange(args); - callArgs[callArgs.Count - 1] = Expression.Assign(result, callArgs[callArgs.Count - 1]); - - return new DynamicMetaObject( - Expression.Block( - new[] { result }, - Expression.Condition( - Expression.Call( - Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), - callArgs - ), - result, - fallbackResult.Expression, - typeof(object) - ) - ), - GetRestrictions().Merge(fallbackResult.Restrictions) - ); - } - - /// - /// Helper method for generating a MetaObject which calls a - /// specific method on Dynamic, but uses one of the arguments for - /// the result. - /// - private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) - { - // - // First, call fallback to do default binding - // This produces either an error or a call to a .NET member - // - DynamicMetaObject fallbackResult = fallback(null); - - IList callArgs = new List(); - callArgs.Add(Expression.Convert(Expression, typeof(T))); - callArgs.Add(Constant(binder)); - callArgs.AddRange(args); - - // - // Build a new expression like: - // if (TryDeleteMember(payload)) { } else { fallbackResult } - // - return new DynamicMetaObject( - Expression.Condition( - Expression.Call( - Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), - callArgs - ), - Expression.Empty(), - fallbackResult.Expression, - typeof(void) - ), - GetRestrictions().Merge(fallbackResult.Restrictions) - ); - } - - /// - /// Returns a Restrictions object which includes our current restrictions merged - /// with a restriction limiting our type - /// - private BindingRestrictions GetRestrictions() - { - return (Value == null && HasValue) - ? BindingRestrictions.GetInstanceRestriction(Expression, null) - : BindingRestrictions.GetTypeRestriction(Expression, LimitType); - } - - public override IEnumerable GetDynamicMemberNames() - { - return _proxy.GetDynamicMemberNames((T)Value); - } - - // It is okay to throw NotSupported from this binder. This object - // is only used by DynamicObject.GetMember--it is not expected to - // (and cannot) implement binding semantics. It is just so the DO - // can use the Name and IgnoreCase properties. - private sealed class GetBinderAdapter : GetMemberBinder - { - internal GetBinderAdapter(InvokeMemberBinder binder) : - base(binder.Name, binder.IgnoreCase) - { - } - - public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) - { - throw new NotSupportedException(); - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs deleted file mode 100644 index b2bfe230d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs +++ /dev/null @@ -1,376 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if NET462 -using System; -using System.Globalization; -using System.Reflection; -using System.Reflection.Emit; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_LINQ -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory - { - internal static DynamicReflectionDelegateFactory Instance { get; } = new(); - - private static DynamicMethod CreateDynamicMethod(string name, Type? returnType, Type[] parameterTypes, Type owner) - { - var dynamicMethod = !owner.IsInterface() - ? new DynamicMethod(name, returnType, parameterTypes, owner, true) - : new DynamicMethod(name, returnType, parameterTypes, owner.Module, true); - - return dynamicMethod; - } - - public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) - { - var dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object[]) }, method.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateMethodCallIL(method, generator, 0); - - return (ObjectConstructor)dynamicMethod.CreateDelegate(typeof(ObjectConstructor)); - } - - public override MethodCall CreateMethodCall(MethodBase method) - { - var dynamicMethod = - CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateMethodCallIL(method, generator, 1); - - return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); - } - - private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex) - { - var args = method.GetParameters(); - - var argsOk = generator.DefineLabel(); - - // throw an error if the number of argument values doesn't match method parameters - generator.Emit(OpCodes.Ldarg, argsIndex); - generator.Emit(OpCodes.Ldlen); - generator.Emit(OpCodes.Ldc_I4, args.Length); - generator.Emit(OpCodes.Beq, argsOk); - generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)); - generator.Emit(OpCodes.Throw); - - generator.MarkLabel(argsOk); - - if (!method.IsConstructor && !method.IsStatic) generator.PushInstance(method.DeclaringType); - - var localConvertible = generator.DeclareLocal(typeof(IConvertible)); - var localObject = generator.DeclareLocal(typeof(object)); - - var variableAddressOpCode = args.Length < 256 ? OpCodes.Ldloca_S : OpCodes.Ldloca; - var variableLoadOpCode = args.Length < 256 ? OpCodes.Ldloc_S : OpCodes.Ldloc; - - for (var i = 0; i < args.Length; i++) - { - var parameter = args[i]; - var parameterType = parameter.ParameterType; - - if (parameterType.IsByRef) - { - parameterType = parameterType.GetElementType(); - - var localVariable = generator.DeclareLocal(parameterType); - - // don't need to set variable for 'out' parameter - if (!parameter.IsOut) - { - generator.PushArrayInstance(argsIndex, i); - - if (parameterType.IsValueType()) - { - var skipSettingDefault = generator.DefineLabel(); - var finishedProcessingParameter = generator.DefineLabel(); - - // check if parameter is not null - generator.Emit(OpCodes.Brtrue_S, skipSettingDefault); - - // parameter has no value, initialize to default - generator.Emit(variableAddressOpCode, localVariable); - generator.Emit(OpCodes.Initobj, parameterType); - generator.Emit(OpCodes.Br_S, finishedProcessingParameter); - - // parameter has value, get value from array again and unbox and set to variable - generator.MarkLabel(skipSettingDefault); - generator.PushArrayInstance(argsIndex, i); - generator.UnboxIfNeeded(parameterType); - generator.Emit(OpCodes.Stloc_S, localVariable); - - // parameter finished, we out! - generator.MarkLabel(finishedProcessingParameter); - } - else - { - generator.UnboxIfNeeded(parameterType); - generator.Emit(OpCodes.Stloc_S, localVariable); - } - } - - generator.Emit(variableAddressOpCode, localVariable); - } - else if (parameterType.IsValueType()) - { - generator.PushArrayInstance(argsIndex, i); - generator.Emit(OpCodes.Stloc_S, localObject); - - // have to check that value type parameters aren't null - // otherwise they will error when unboxed - var skipSettingDefault = generator.DefineLabel(); - var finishedProcessingParameter = generator.DefineLabel(); - - // check if parameter is not null - generator.Emit(OpCodes.Ldloc_S, localObject); - generator.Emit(OpCodes.Brtrue_S, skipSettingDefault); - - // parameter has no value, initialize to default - var localVariable = generator.DeclareLocal(parameterType); - generator.Emit(variableAddressOpCode, localVariable); - generator.Emit(OpCodes.Initobj, parameterType); - generator.Emit(variableLoadOpCode, localVariable); - generator.Emit(OpCodes.Br_S, finishedProcessingParameter); - - // argument has value, try to convert it to parameter type - generator.MarkLabel(skipSettingDefault); - - if (parameterType.IsPrimitive()) - { - // for primitive types we need to handle type widening (e.g. short -> int) - var toParameterTypeMethod = typeof(IConvertible) - .GetMethod("To" + parameterType.Name, new[] { typeof(IFormatProvider) }); - - if (toParameterTypeMethod != null) - { - var skipConvertible = generator.DefineLabel(); - - // check if argument type is an exact match for parameter type - // in this case we may use cheap unboxing instead - generator.Emit(OpCodes.Ldloc_S, localObject); - generator.Emit(OpCodes.Isinst, parameterType); - generator.Emit(OpCodes.Brtrue_S, skipConvertible); - - // types don't match, check if argument implements IConvertible - generator.Emit(OpCodes.Ldloc_S, localObject); - generator.Emit(OpCodes.Isinst, typeof(IConvertible)); - generator.Emit(OpCodes.Stloc_S, localConvertible); - generator.Emit(OpCodes.Ldloc_S, localConvertible); - generator.Emit(OpCodes.Brfalse_S, skipConvertible); - - // convert argument to parameter type - generator.Emit(OpCodes.Ldloc_S, localConvertible); - generator.Emit(OpCodes.Ldnull); - generator.Emit(OpCodes.Callvirt, toParameterTypeMethod); - generator.Emit(OpCodes.Br_S, finishedProcessingParameter); - - generator.MarkLabel(skipConvertible); - } - } - - // we got here because either argument type matches parameter (conversion will succeed), - // or argument type doesn't match parameter, but we're out of options (conversion will fail) - generator.Emit(OpCodes.Ldloc_S, localObject); - - generator.UnboxIfNeeded(parameterType); - - // parameter finished, we out! - generator.MarkLabel(finishedProcessingParameter); - } - else - { - generator.PushArrayInstance(argsIndex, i); - - generator.UnboxIfNeeded(parameterType); - } - } - - if (method.IsConstructor) - generator.Emit(OpCodes.Newobj, (ConstructorInfo)method); - else - generator.CallMethod((MethodInfo)method); - - var returnType = method.IsConstructor - ? method.DeclaringType - : ((MethodInfo)method).ReturnType; - - if (returnType != typeof(void)) - generator.BoxIfNeeded(returnType); - else - generator.Emit(OpCodes.Ldnull); - - generator.Return(); - } - - public override Func CreateDefaultConstructor(Type type) - { - var dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), ReflectionUtils.EmptyTypes, type); - dynamicMethod.InitLocals = true; - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateDefaultConstructorIL(type, generator, typeof(T)); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); - } - - private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator, Type delegateType) - { - if (type.IsValueType()) - { - generator.DeclareLocal(type); - generator.Emit(OpCodes.Ldloc_0); - - // only need to box if the delegate isn't returning the value type - if (type != delegateType) generator.Emit(OpCodes.Box, type); - } - else - { - var constructorInfo = - type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, ReflectionUtils.EmptyTypes, null); - - if (constructorInfo == null) - throw new ArgumentException("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type)); - - generator.Emit(OpCodes.Newobj, constructorInfo); - } - - generator.Return(); - } - - public override Func CreateGet(PropertyInfo propertyInfo) - { - var dynamicMethod = - CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new[] { typeof(T) }, propertyInfo.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateGetPropertyIL(propertyInfo, generator); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); - } - - private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) - { - var getMethod = propertyInfo.GetGetMethod(true); - if (getMethod == null) - throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name)); - - if (!getMethod.IsStatic) generator.PushInstance(propertyInfo.DeclaringType); - - generator.CallMethod(getMethod); - generator.BoxIfNeeded(propertyInfo.PropertyType); - generator.Return(); - } - - public override Func CreateGet(FieldInfo fieldInfo) - { - if (fieldInfo.IsLiteral) - { - var constantValue = fieldInfo.GetValue(null); - Func getter = o => constantValue; - return getter; - } - - var dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateGetFieldIL(fieldInfo, generator); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); - } - - private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator) - { - if (!fieldInfo.IsStatic) - { - generator.PushInstance(fieldInfo.DeclaringType); - generator.Emit(OpCodes.Ldfld, fieldInfo); - } - else - generator.Emit(OpCodes.Ldsfld, fieldInfo); - - generator.BoxIfNeeded(fieldInfo.FieldType); - generator.Return(); - } - - public override Action CreateSet(FieldInfo fieldInfo) - { - var dynamicMethod = - CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateSetFieldIL(fieldInfo, generator); - - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); - } - - internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator) - { - if (!fieldInfo.IsStatic) generator.PushInstance(fieldInfo.DeclaringType); - - generator.Emit(OpCodes.Ldarg_1); - generator.UnboxIfNeeded(fieldInfo.FieldType); - - if (!fieldInfo.IsStatic) - generator.Emit(OpCodes.Stfld, fieldInfo); - else - generator.Emit(OpCodes.Stsfld, fieldInfo); - - generator.Return(); - } - - public override Action CreateSet(PropertyInfo propertyInfo) - { - var dynamicMethod = - CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); - var generator = dynamicMethod.GetILGenerator(); - - GenerateCreateSetPropertyIL(propertyInfo, generator); - - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); - } - - internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) - { - var setMethod = propertyInfo.GetSetMethod(true); - if (!setMethod.IsStatic) generator.PushInstance(propertyInfo.DeclaringType); - - generator.Emit(OpCodes.Ldarg_1); - generator.UnboxIfNeeded(propertyInfo.PropertyType); - generator.CallMethod(setMethod); - generator.Return(); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicUtils.cs deleted file mode 100644 index ad5f85316..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/DynamicUtils.cs +++ /dev/null @@ -1,218 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_DYNAMIC -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Linq.Expressions; -#if !HAVE_REFLECTION_BINDER -using System.Reflection; -#else -using Microsoft.CSharp.RuntimeBinder; -#endif -using System.Runtime.CompilerServices; -using System.Globalization; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class DynamicUtils - { - internal static class BinderWrapper - { -#if !HAVE_REFLECTION_BINDER - public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; - - private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, " + CSharpAssemblyName; - private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, " + CSharpAssemblyName; - private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, " + CSharpAssemblyName; - private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, " + CSharpAssemblyName; - - private static object? _getCSharpArgumentInfoArray; - private static object? _setCSharpArgumentInfoArray; - private static MethodCall? _getMemberCall; - private static MethodCall? _setMemberCall; - private static bool _init; - - private static void Init() - { - if (!_init) - { - Type binderType = Type.GetType(BinderTypeName, false); - if (binderType == null) - { - throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName)); - } - - // None - _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0); - // None, Constant | UseCompileTimeType - _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3); - CreateMemberCalls(); - - _init = true; - } - } - - private static object CreateSharpArgumentInfoArray(params int[] values) - { - Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName); - Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName); - - Array a = Array.CreateInstance(csharpArgumentInfoType, values.Length); - - for (int i = 0; i < values.Length; i++) - { - MethodInfo createArgumentInfoMethod = - csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) }); - object arg = createArgumentInfoMethod.Invoke(null, new object?[] { 0, null }); - a.SetValue(arg, i); - } - - return a; - } - - private static void CreateMemberCalls() - { - Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true); - Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName, true); - Type binderType = Type.GetType(BinderTypeName, true); - - Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType); - - MethodInfo getMemberMethod = - binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); - _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getMemberMethod); - - MethodInfo setMemberMethod = - binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); - _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMemberMethod); - } -#endif - - public static CallSiteBinder GetMember(string name, Type context) - { -#if !HAVE_REFLECTION_BINDER - Init(); - MiscellaneousUtils.Assert(_getMemberCall != null); - MiscellaneousUtils.Assert(_getCSharpArgumentInfoArray != null); - return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray)!; -#else - return Binder.GetMember( - CSharpBinderFlags.None, name, context, new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}); -#endif - } - - public static CallSiteBinder SetMember(string name, Type context) - { -#if !HAVE_REFLECTION_BINDER - Init(); - MiscellaneousUtils.Assert(_setMemberCall != null); - MiscellaneousUtils.Assert(_setCSharpArgumentInfoArray != null); - return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray)!; -#else - return Binder.SetMember( - CSharpBinderFlags.None, name, context, new[] - { - CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null), - CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) - }); -#endif - } - } - - public static IEnumerable GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider) - { - DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider)); - return metaObject.GetDynamicMemberNames(); - } - } - - internal class NoThrowGetBinderMember : GetMemberBinder - { - private readonly GetMemberBinder _innerBinder; - - public NoThrowGetBinderMember(GetMemberBinder innerBinder) - : base(innerBinder.Name, innerBinder.IgnoreCase) - { - _innerBinder = innerBinder; - } - - public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) - { - DynamicMetaObject retMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty()); - - NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor(); - Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression); - - DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions); - return finalMetaObject; - } - } - - internal class NoThrowSetBinderMember : SetMemberBinder - { - private readonly SetMemberBinder _innerBinder; - - public NoThrowSetBinderMember(SetMemberBinder innerBinder) - : base(innerBinder.Name, innerBinder.IgnoreCase) - { - _innerBinder = innerBinder; - } - - public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) - { - DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value }); - - NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor(); - Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression); - - DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions); - return finalMetaObject; - } - } - - internal class NoThrowExpressionVisitor : ExpressionVisitor - { - internal static readonly object ErrorResult = new object(); - - protected override Expression VisitConditional(ConditionalExpression node) - { - // if the result of a test is to throw an error, rewrite to result an error result value - if (node.IfFalse.NodeType == ExpressionType.Throw) - { - return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult)); - } - - return base.VisitConditional(node); - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumInfo.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumInfo.cs deleted file mode 100644 index 8f19e35c0..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumInfo.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class EnumInfo - { - public readonly bool IsFlags; - public readonly string[] Names; - public readonly string[] ResolvedNames; - public readonly ulong[] Values; - - public EnumInfo(bool isFlags, ulong[] values, string[] names, string[] resolvedNames) - { - IsFlags = isFlags; - Values = values; - Names = names; - ResolvedNames = resolvedNames; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumUtils.cs deleted file mode 100644 index 34ec2651d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/EnumUtils.cs +++ /dev/null @@ -1,358 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Reflection; -using System.Runtime.Serialization; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class EnumUtils - { - private const char EnumSeparatorChar = ','; - private const string EnumSeparatorString = ", "; - - private static readonly ThreadSafeStore, EnumInfo> - ValuesAndNamesPerEnum = new(InitializeValuesAndNames); - - private static readonly CamelCaseNamingStrategy _camelCaseNamingStrategy = new(); - - // Used by Newtonsoft.Json.Schema - - - private static EnumInfo InitializeValuesAndNames(StructMultiKey key) - { - var enumType = key.Value1; - var names = Enum.GetNames(enumType); - var resolvedNames = new string[names.Length]; - var values = new ulong[names.Length]; - bool hasSpecifiedName; - - for (var i = 0; i < names.Length; i++) - { - var name = names[i]; - var f = enumType.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)!; - values[i] = ToUInt64(f.GetValue(null)); - - string resolvedName; -#if HAVE_DATA_CONTRACTS - string specifiedName = f.GetCustomAttributes(typeof(EnumMemberAttribute), true) - .Cast() - .Select(a => a.Value) - .SingleOrDefault(); - hasSpecifiedName = specifiedName != null; - resolvedName = specifiedName ?? name; - - if (Array.IndexOf(resolvedNames, resolvedName, 0, i) != -1) - { - throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, resolvedName, enumType.Name)); - } -#else - resolvedName = name; - hasSpecifiedName = false; -#endif - - resolvedNames[i] = key.Value2 != null - ? key.Value2.GetPropertyName(resolvedName, hasSpecifiedName) - : resolvedName; - } - - var isFlags = enumType.IsDefined(typeof(FlagsAttribute), false); - - return new EnumInfo(isFlags, values, names, resolvedNames); - } - - public static IList GetFlagsValues(T value) where T : struct - { - var enumType = typeof(T); - - if (!enumType.IsDefined(typeof(FlagsAttribute), false)) - throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, enumType)); - - var underlyingType = Enum.GetUnderlyingType(value.GetType()); - - var num = ToUInt64(value); - var enumNameValues = GetEnumValuesAndNames(enumType); - IList selectedFlagsValues = new List(); - - for (var i = 0; i < enumNameValues.Values.Length; i++) - { - var v = enumNameValues.Values[i]; - - if ((num & v) == v && v != 0) selectedFlagsValues.Add((T)Convert.ChangeType(v, underlyingType, CultureInfo.CurrentCulture)); - } - - if (selectedFlagsValues.Count == 0 && enumNameValues.Values.Any(v => v == 0)) selectedFlagsValues.Add(default); - - return selectedFlagsValues; - } - - public static bool TryToString(Type enumType, object value, bool camelCase, [NotNullWhen(true)] out string? name) => - TryToString(enumType, value, camelCase ? _camelCaseNamingStrategy : null, out name); - - public static bool TryToString(Type enumType, object value, NamingStrategy? namingStrategy, [NotNullWhen(true)] out string? name) - { - var enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); - var v = ToUInt64(value); - - if (!enumInfo.IsFlags) - { - var index = Array.BinarySearch(enumInfo.Values, v); - if (index >= 0) - { - name = enumInfo.ResolvedNames[index]; - return true; - } - - // is number value - name = null; - return false; - } - name = InternalFlagsFormat(enumInfo, v); - return name != null; - } - - private static string? InternalFlagsFormat(EnumInfo entry, ulong result) - { - var resolvedNames = entry.ResolvedNames; - var values = entry.Values; - - var index = values.Length - 1; - var sb = new StringBuilder(); - var firstTime = true; - var saveResult = result; - - // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied - // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of - // items in an enum are sufficiently small and not worth the optimization. - while (index >= 0) - { - if (index == 0 && values[index] == 0) break; - - if ((result & values[index]) == values[index]) - { - result -= values[index]; - if (!firstTime) sb.Insert(0, EnumSeparatorString); - - var resolvedName = resolvedNames[index]; - sb.Insert(0, resolvedName); - firstTime = false; - } - - index--; - } - - string? returnString; - if (result != 0) - { - // We were unable to represent this number as a bitwise or of valid flags - returnString = null; // return null so the caller knows to .ToString() the input - } - else if (saveResult == 0) - { - // For the cases when we have zero - if (values.Length > 0 && values[0] == 0) - returnString = resolvedNames[0]; // Zero was one of the enum values. - else - returnString = null; - } - else - returnString = sb.ToString(); // Return the string representation - - return returnString; - } - - public static EnumInfo GetEnumValuesAndNames(Type enumType) => - ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, null)); - - private static ulong ToUInt64(object value) - { - var typeCode = ConvertUtils.GetTypeCode(value.GetType(), out var _); - - switch (typeCode) - { - case PrimitiveTypeCode.SByte: - return (ulong)(sbyte)value; - case PrimitiveTypeCode.Byte: - return (byte)value; - case PrimitiveTypeCode.Boolean: - // direct cast from bool to byte is not allowed - return Convert.ToByte((bool)value); - case PrimitiveTypeCode.Int16: - return (ulong)(short)value; - case PrimitiveTypeCode.UInt16: - return (ushort)value; - case PrimitiveTypeCode.Char: - return (char)value; - case PrimitiveTypeCode.UInt32: - return (uint)value; - case PrimitiveTypeCode.Int32: - return (ulong)(int)value; - case PrimitiveTypeCode.UInt64: - return (ulong)value; - case PrimitiveTypeCode.Int64: - return (ulong)(long)value; - // All unsigned types will be directly cast - default: - throw new InvalidOperationException("Unknown enum type."); - } - } - - public static object ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber) - { - ValidationUtils.ArgumentNotNull(enumType, nameof(enumType)); - ValidationUtils.ArgumentNotNull(value, nameof(value)); - - if (!enumType.IsEnum()) throw new ArgumentException("Type provided must be an Enum.", nameof(enumType)); - - var entry = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); - var enumNames = entry.Names; - var resolvedNames = entry.ResolvedNames; - var enumValues = entry.Values; - - // first check if the entire text (including commas) matches a resolved name - var matchingIndex = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.Ordinal); - if (matchingIndex != null) return Enum.ToObject(enumType, enumValues[matchingIndex.Value]); - - var firstNonWhitespaceIndex = -1; - for (var i = 0; i < value.Length; i++) - { - if (!char.IsWhiteSpace(value[i])) - { - firstNonWhitespaceIndex = i; - break; - } - } - if (firstNonWhitespaceIndex == -1) throw new ArgumentException("Must specify valid information for parsing in the string."); - - // check whether string is a number and parse as a number value - var firstNonWhitespaceChar = value[firstNonWhitespaceIndex]; - if (char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '-' || firstNonWhitespaceChar == '+') - { - var underlyingType = Enum.GetUnderlyingType(enumType); - - value = value.Trim(); - object? temp = null; - - try - { - temp = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); - } - catch (FormatException) - { - // We need to Parse this as a String instead. There are cases - // when you tlbimp enums that can have values of the form "3D". - // Don't fix this code. - } - - if (temp != null) - { - if (disallowNumber) - throw new FormatException("Integer string '{0}' is not allowed.".FormatWith(CultureInfo.InvariantCulture, value)); - - return Enum.ToObject(enumType, temp); - } - } - - ulong result = 0; - - var valueIndex = firstNonWhitespaceIndex; - while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma - { - // Find the next separator, if there is one, otherwise the end of the string. - var endIndex = value.IndexOf(EnumSeparatorChar, valueIndex); - if (endIndex == -1) endIndex = value.Length; - - // Shift the starting and ending indices to eliminate whitespace - var endIndexNoWhitespace = endIndex; - while (valueIndex < endIndex && char.IsWhiteSpace(value[valueIndex])) valueIndex++; - - while (endIndexNoWhitespace > valueIndex && char.IsWhiteSpace(value[endIndexNoWhitespace - 1])) endIndexNoWhitespace--; - var valueSubstringLength = endIndexNoWhitespace - valueIndex; - - // match with case sensitivity - matchingIndex = MatchName(value, enumNames, resolvedNames, valueIndex, valueSubstringLength, StringComparison.Ordinal); - - // if no match found, attempt case insensitive search - if (matchingIndex == null) - matchingIndex = MatchName(value, enumNames, resolvedNames, valueIndex, valueSubstringLength, StringComparison.OrdinalIgnoreCase); - - if (matchingIndex == null) - { - // still can't find a match - // before we throw an error, check whether the entire string has a case insensitive match against resolve names - matchingIndex = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.OrdinalIgnoreCase); - if (matchingIndex != null) return Enum.ToObject(enumType, enumValues[matchingIndex.Value]); - - // no match so error - throw new ArgumentException("Requested value '{0}' was not found.".FormatWith(CultureInfo.InvariantCulture, value)); - } - - result |= enumValues[matchingIndex.Value]; - - // Move our pointer to the ending index to go again. - valueIndex = endIndex + 1; - } - - return Enum.ToObject(enumType, result); - } - - private static int? MatchName(string value, string[] enumNames, string[] resolvedNames, int valueIndex, int valueSubstringLength, - StringComparison comparison - ) - { - var matchingIndex = FindIndexByName(resolvedNames, value, valueIndex, valueSubstringLength, comparison); - if (matchingIndex == null) matchingIndex = FindIndexByName(enumNames, value, valueIndex, valueSubstringLength, comparison); - - return matchingIndex; - } - - private static int? FindIndexByName(string[] enumNames, string value, int valueIndex, int valueSubstringLength, StringComparison comparison) - { - for (var i = 0; i < enumNames.Length; i++) - { - if (enumNames[i].Length == valueSubstringLength && - string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0) - return i; - } - - return null; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs deleted file mode 100644 index e5d72d72d..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs +++ /dev/null @@ -1,365 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if !(NET20 || NET35) - -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class ExpressionReflectionDelegateFactory : ReflectionDelegateFactory - { - private static readonly ExpressionReflectionDelegateFactory _instance = new(); - - internal static ReflectionDelegateFactory Instance => _instance; - - public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) - { - ValidationUtils.ArgumentNotNull(method, nameof(method)); - - var type = typeof(object); - - var argsParameterExpression = Expression.Parameter(typeof(object[]), "args"); - - var callExpression = BuildMethodCall(method, type, null, argsParameterExpression); - - var lambdaExpression = Expression.Lambda(typeof(ObjectConstructor), callExpression, argsParameterExpression); - - var compiled = (ObjectConstructor)lambdaExpression.Compile(); - return compiled; - } - - public override MethodCall CreateMethodCall(MethodBase method) - { - ValidationUtils.ArgumentNotNull(method, nameof(method)); - - var type = typeof(object); - - var targetParameterExpression = Expression.Parameter(type, "target"); - var argsParameterExpression = Expression.Parameter(typeof(object[]), "args"); - - var callExpression = BuildMethodCall(method, type, targetParameterExpression, argsParameterExpression); - - var lambdaExpression = - Expression.Lambda(typeof(MethodCall), callExpression, targetParameterExpression, argsParameterExpression); - - var compiled = (MethodCall)lambdaExpression.Compile(); - return compiled; - } - - private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression? targetParameterExpression, - ParameterExpression argsParameterExpression - ) - { - var parametersInfo = method.GetParameters(); - - Expression[] argsExpression; - IList refParameterMap; - if (parametersInfo.Length == 0) - { - argsExpression = CollectionUtils.ArrayEmpty(); - refParameterMap = CollectionUtils.ArrayEmpty(); - } - else - { - argsExpression = new Expression[parametersInfo.Length]; - refParameterMap = new List(); - - for (var i = 0; i < parametersInfo.Length; i++) - { - var parameter = parametersInfo[i]; - var parameterType = parameter.ParameterType; - var isByRef = false; - if (parameterType.IsByRef) - { - parameterType = parameterType.GetElementType(); - isByRef = true; - } - - Expression indexExpression = Expression.Constant(i); - - Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression); - - var argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef); - - if (isByRef) - { - var variable = Expression.Variable(parameterType); - refParameterMap.Add(new ByRefParameter(argExpression, variable, parameter.IsOut)); - - argExpression = variable; - } - - argsExpression[i] = argExpression; - } - } - - Expression callExpression; - if (method.IsConstructor) - callExpression = Expression.New((ConstructorInfo)method, argsExpression); - else if (method.IsStatic) - callExpression = Expression.Call((MethodInfo)method, argsExpression); - else - { - var readParameter = EnsureCastExpression(targetParameterExpression!, method.DeclaringType); - - callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression); - } - - if (method is MethodInfo m) - { - if (m.ReturnType != typeof(void)) - callExpression = EnsureCastExpression(callExpression, type); - else - callExpression = Expression.Block(callExpression, Expression.Constant(null)); - } - else - callExpression = EnsureCastExpression(callExpression, type); - - if (refParameterMap.Count > 0) - { - IList variableExpressions = new List(); - IList bodyExpressions = new List(); - foreach (var p in refParameterMap) - { - if (!p.IsOut) bodyExpressions.Add(Expression.Assign(p.Variable, p.Value)); - - variableExpressions.Add(p.Variable); - } - - bodyExpressions.Add(callExpression); - - callExpression = Expression.Block(variableExpressions, bodyExpressions); - } - - return callExpression; - } - - public override Func CreateDefaultConstructor(Type type) - { - ValidationUtils.ArgumentNotNull(type, "type"); - - // avoid error from expressions compiler because of abstract class - if (type.IsAbstract()) return () => (T)Activator.CreateInstance(type); - - try - { - var resultType = typeof(T); - - Expression expression = Expression.New(type); - - expression = EnsureCastExpression(expression, resultType); - - var lambdaExpression = Expression.Lambda(typeof(Func), expression); - - var compiled = (Func)lambdaExpression.Compile(); - return compiled; - } - catch - { - // an error can be thrown if constructor is not valid on Win8 - // will have INVOCATION_FLAGS_NON_W8P_FX_API invocation flag - return () => (T)Activator.CreateInstance(type); - } - } - - public override Func CreateGet(PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - var instanceType = typeof(T); - var resultType = typeof(object); - - var parameterExpression = Expression.Parameter(instanceType, "instance"); - Expression resultExpression; - - var getMethod = propertyInfo.GetGetMethod(true); - if (getMethod == null) throw new ArgumentException("Property does not have a getter."); - - if (getMethod.IsStatic) - resultExpression = Expression.MakeMemberAccess(null, propertyInfo); - else - { - var readParameter = EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType); - - resultExpression = Expression.MakeMemberAccess(readParameter, propertyInfo); - } - - resultExpression = EnsureCastExpression(resultExpression, resultType); - - var lambdaExpression = Expression.Lambda(typeof(Func), resultExpression, parameterExpression); - - var compiled = (Func)lambdaExpression.Compile(); - return compiled; - } - - public override Func CreateGet(FieldInfo fieldInfo) - { - ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); - - var sourceParameter = Expression.Parameter(typeof(T), "source"); - - Expression fieldExpression; - if (fieldInfo.IsStatic) - fieldExpression = Expression.Field(null, fieldInfo); - else - { - var sourceExpression = EnsureCastExpression(sourceParameter, fieldInfo.DeclaringType); - - fieldExpression = Expression.Field(sourceExpression, fieldInfo); - } - - fieldExpression = EnsureCastExpression(fieldExpression, typeof(object)); - - var compiled = Expression.Lambda>(fieldExpression, sourceParameter).Compile(); - return compiled; - } - - public override Action CreateSet(FieldInfo fieldInfo) - { - ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); - - // use reflection for structs - // expression doesn't correctly set value - if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly) - return LateBoundReflectionDelegateFactory.Instance.CreateSet(fieldInfo); - - var sourceParameterExpression = Expression.Parameter(typeof(T), "source"); - var valueParameterExpression = Expression.Parameter(typeof(object), "value"); - - Expression fieldExpression; - if (fieldInfo.IsStatic) - fieldExpression = Expression.Field(null, fieldInfo); - else - { - var sourceExpression = EnsureCastExpression(sourceParameterExpression, fieldInfo.DeclaringType); - - fieldExpression = Expression.Field(sourceExpression, fieldInfo); - } - - var valueExpression = EnsureCastExpression(valueParameterExpression, fieldExpression.Type); - - var assignExpression = Expression.Assign(fieldExpression, valueExpression); - - var lambdaExpression = - Expression.Lambda(typeof(Action), assignExpression, sourceParameterExpression, valueParameterExpression); - - var compiled = (Action)lambdaExpression.Compile(); - return compiled; - } - - public override Action CreateSet(PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - // use reflection for structs - // expression doesn't correctly set value - if (propertyInfo.DeclaringType.IsValueType()) return LateBoundReflectionDelegateFactory.Instance.CreateSet(propertyInfo); - - var instanceType = typeof(T); - var valueType = typeof(object); - - var instanceParameter = Expression.Parameter(instanceType, "instance"); - - var valueParameter = Expression.Parameter(valueType, "value"); - var readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType); - - var setMethod = propertyInfo.GetSetMethod(true); - if (setMethod == null) throw new ArgumentException("Property does not have a setter."); - - Expression setExpression; - if (setMethod.IsStatic) - setExpression = Expression.Call(setMethod, readValueParameter); - else - { - var readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType); - - setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter); - } - - var lambdaExpression = Expression.Lambda(typeof(Action), setExpression, instanceParameter, valueParameter); - - var compiled = (Action)lambdaExpression.Compile(); - return compiled; - } - - private Expression EnsureCastExpression(Expression expression, Type targetType, bool allowWidening = false) - { - var expressionType = expression.Type; - - // check if a cast or conversion is required - if (expressionType == targetType || !expressionType.IsValueType() && targetType.IsAssignableFrom(expressionType)) return expression; - - if (targetType.IsValueType()) - { - Expression convert = Expression.Unbox(expression, targetType); - - if (allowWidening && targetType.IsPrimitive()) - { - var toTargetTypeMethod = typeof(Convert) - .GetMethod("To" + targetType.Name, new[] { typeof(object) }); - - if (toTargetTypeMethod != null) - { - convert = Expression.Condition( - Expression.TypeIs(expression, targetType), - convert, - Expression.Call(toTargetTypeMethod, expression)); - } - } - - return Expression.Condition( - Expression.Equal(expression, Expression.Constant(null, typeof(object))), - Expression.Default(targetType), - convert); - } - - return Expression.Convert(expression, targetType); - } - - private class ByRefParameter - { - public readonly bool IsOut; - public readonly Expression Value; - public readonly ParameterExpression Variable; - - public ByRefParameter(Expression value, ParameterExpression variable, bool isOut) - { - Value = value; - Variable = variable; - IsOut = isOut; - } - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/FSharpUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/FSharpUtils.cs deleted file mode 100644 index 968c5dc99..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/FSharpUtils.cs +++ /dev/null @@ -1,207 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_FSHARP_TYPES -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class FSharpFunction - { - private readonly object? _instance; - private readonly MethodCall _invoker; - - public FSharpFunction(object? instance, MethodCall invoker) - { - _instance = instance; - _invoker = invoker; - } - - public object Invoke(params object[] args) - { - object o = _invoker(_instance, args); - - return o; - } - } - - internal class FSharpUtils - { - private FSharpUtils(Assembly fsharpCoreAssembly) - { - FSharpCoreAssembly = fsharpCoreAssembly; - - Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType"); - - MethodInfo isUnionMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "IsUnion", BindingFlags.Public | BindingFlags.Static); - IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(isUnionMethodInfo)!; - - MethodInfo getUnionCasesMethodInfo = - GetMethodWithNonPublicFallback(fsharpType, "GetUnionCases", BindingFlags.Public | BindingFlags.Static); - GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getUnionCasesMethodInfo)!; - - Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue"); - - PreComputeUnionTagReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionTagReader"); - PreComputeUnionReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionReader"); - PreComputeUnionConstructor = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionConstructor"); - - Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo"); - - GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Name")!)!; - GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Tag")!)!; - GetUnionCaseInfoDeclaringType = - JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("DeclaringType")!)!; - GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(unionCaseInfo.GetMethod("GetFields")); - - Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule"); - _ofSeq = listModule.GetMethod("OfSeq"); - - _mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2"); - } - - private static readonly object Lock = new object(); - private static FSharpUtils? _instance; - - public static FSharpUtils Instance - { - get - { - MiscellaneousUtils.Assert(_instance != null); - return _instance; - } - } - - private MethodInfo _ofSeq; - private Type _mapType; - - public Assembly FSharpCoreAssembly { get; private set; } - public MethodCall IsUnion { get; private set; } - public MethodCall GetUnionCases { get; private set; } - public MethodCall PreComputeUnionTagReader { get; private set; } - public MethodCall PreComputeUnionReader { get; private set; } - public MethodCall PreComputeUnionConstructor { get; private set; } - public Func GetUnionCaseInfoDeclaringType { get; private set; } - public Func GetUnionCaseInfoName { get; private set; } - public Func GetUnionCaseInfoTag { get; private set; } - public MethodCall GetUnionCaseInfoFields { get; private set; } - - public const string FSharpSetTypeName = "FSharpSet`1"; - public const string FSharpListTypeName = "FSharpList`1"; - public const string FSharpMapTypeName = "FSharpMap`2"; - - public static void EnsureInitialized(Assembly fsharpCoreAssembly) - { - if (_instance == null) - { - lock (Lock) - { - if (_instance == null) - { - _instance = new FSharpUtils(fsharpCoreAssembly); - } - } - } - } - - private static MethodInfo GetMethodWithNonPublicFallback(Type type, string methodName, BindingFlags bindingFlags) - { - MethodInfo methodInfo = type.GetMethod(methodName, bindingFlags); - - // if no matching method then attempt to find with nonpublic flag - // this is required because in WinApps some methods are private but always using NonPublic breaks medium trust - // https://github.com/JamesNK/Newtonsoft.Json/pull/649 - // https://github.com/JamesNK/Newtonsoft.Json/issues/821 - if (methodInfo == null && (bindingFlags & BindingFlags.NonPublic) != BindingFlags.NonPublic) - { - methodInfo = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic); - } - - return methodInfo!; - } - - private static MethodCall CreateFSharpFuncCall(Type type, string methodName) - { - MethodInfo innerMethodInfo = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Public | BindingFlags.Static); - MethodInfo invokeFunc = innerMethodInfo.ReturnType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance); - - MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(innerMethodInfo); - MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(invokeFunc)!; - - MethodCall createFunction = (target, args) => - { - object? result = call(target, args); - - FSharpFunction f = new FSharpFunction(result, invoke); - return f; - }; - - return createFunction; - } - - public ObjectConstructor CreateSeq(Type t) - { - MethodInfo seqType = _ofSeq.MakeGenericMethod(t); - - return JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(seqType); - } - - public ObjectConstructor CreateMap(Type keyType, Type valueType) - { - MethodInfo creatorDefinition = typeof(FSharpUtils).GetMethod("BuildMapCreator"); - - MethodInfo creatorGeneric = creatorDefinition.MakeGenericMethod(keyType, valueType); - - return (ObjectConstructor)creatorGeneric.Invoke(this, null); - } - - public ObjectConstructor BuildMapCreator() - { - Type genericMapType = _mapType.MakeGenericType(typeof(TKey), typeof(TValue)); - ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable>) }); - ObjectConstructor ctorDelegate = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(ctor); - - ObjectConstructor creator = args => - { - // convert dictionary KeyValuePairs to Tuples - IEnumerable> values = (IEnumerable>)args[0]!; - IEnumerable> tupleValues = values.Select(kv => new Tuple(kv.Key, kv.Value)); - - return ctorDelegate(tupleValues); - }; - - return creator; - } - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs deleted file mode 100644 index ae497b467..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs +++ /dev/null @@ -1,82 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if NET462 -using System; -using System.Reflection; -using System.Reflection.Emit; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class ILGeneratorExtensions - { - public static void PushInstance(this ILGenerator generator, Type type) - { - generator.Emit(OpCodes.Ldarg_0); - if (type.IsValueType()) - generator.Emit(OpCodes.Unbox, type); - else - generator.Emit(OpCodes.Castclass, type); - } - - public static void PushArrayInstance(this ILGenerator generator, int argsIndex, int arrayIndex) - { - generator.Emit(OpCodes.Ldarg, argsIndex); - generator.Emit(OpCodes.Ldc_I4, arrayIndex); - generator.Emit(OpCodes.Ldelem_Ref); - } - - public static void BoxIfNeeded(this ILGenerator generator, Type type) - { - if (type.IsValueType()) - generator.Emit(OpCodes.Box, type); - else - generator.Emit(OpCodes.Castclass, type); - } - - public static void UnboxIfNeeded(this ILGenerator generator, Type type) - { - if (type.IsValueType()) - generator.Emit(OpCodes.Unbox_Any, type); - else - generator.Emit(OpCodes.Castclass, type); - } - - public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo) - { - if (methodInfo.IsFinal || !methodInfo.IsVirtual) - generator.Emit(OpCodes.Call, methodInfo); - else - generator.Emit(OpCodes.Callvirt, methodInfo); - } - - public static void Return(this ILGenerator generator) => generator.Emit(OpCodes.Ret); - } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs deleted file mode 100644 index 2ba3941fd..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs +++ /dev/null @@ -1,193 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - /// - /// Helper class for serializing immutable collections. - /// Note that this is used by all builds, even those that don't support immutable collections, in case the DLL is GACed - /// https://github.com/JamesNK/Newtonsoft.Json/issues/652 - /// - internal static class ImmutableCollectionsUtils - { - private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1"; - - private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray"; - - private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2"; - private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2"; - - private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary"; - private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1"; - - private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet"; - - private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1"; - private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1"; - - private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList"; - private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1"; - private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1"; - - private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue"; - private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1"; - private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2"; - - private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary"; - private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1"; - - private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet"; - private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1"; - private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1"; - - private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack"; - - private static readonly IList ArrayContractImmutableCollectionDefinitions = new List - { - new(ImmutableListGenericInterfaceTypeName, ImmutableListGenericTypeName, ImmutableListTypeName), - new(ImmutableListGenericTypeName, ImmutableListGenericTypeName, ImmutableListTypeName), - new(ImmutableQueueGenericInterfaceTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName), - new(ImmutableQueueGenericTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName), - new(ImmutableStackGenericInterfaceTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName), - new(ImmutableStackGenericTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName), - new(ImmutableSetGenericInterfaceTypeName, ImmutableHashSetGenericTypeName, ImmutableHashSetTypeName), - new(ImmutableSortedSetGenericTypeName, ImmutableSortedSetGenericTypeName, ImmutableSortedSetTypeName), - new(ImmutableHashSetGenericTypeName, ImmutableHashSetGenericTypeName, ImmutableHashSetTypeName), - new(ImmutableArrayGenericTypeName, ImmutableArrayGenericTypeName, ImmutableArrayTypeName) - }; - - private static readonly IList DictionaryContractImmutableCollectionDefinitions = - new List - { - new(ImmutableDictionaryGenericInterfaceTypeName, ImmutableDictionaryGenericTypeName, ImmutableDictionaryTypeName), - new(ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryTypeName), - new(ImmutableDictionaryGenericTypeName, ImmutableDictionaryGenericTypeName, ImmutableDictionaryTypeName) - }; - - internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, - [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator - ) - { - if (underlyingType.IsGenericType()) - { - var underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition(); - var name = underlyingTypeDefinition.FullName; - - var definition = ArrayContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); - if (definition != null) - { - var createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); - var builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); - - if (createdTypeDefinition != null && builderTypeDefinition != null) - { - var mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => m.Name == "CreateRange" && m.GetParameters().Length == 1); - if (mb != null) - { - createdType = createdTypeDefinition.MakeGenericType(collectionItemType); - var method = mb.MakeGenericMethod(collectionItemType); - parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); - return true; - } - } - } - } - - createdType = null; - parameterizedCreator = null; - return false; - } - - internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, - [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator - ) - { - if (underlyingType.IsGenericType()) - { - var underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition(); - var name = underlyingTypeDefinition.FullName; - - var definition = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); - if (definition != null) - { - var createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); - var builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); - - if (createdTypeDefinition != null && builderTypeDefinition != null) - { - var mb = builderTypeDefinition.GetMethods() - .FirstOrDefault(m => - { - var parameters = m.GetParameters(); - - return m.Name == "CreateRange" && parameters.Length == 1 && parameters[0].ParameterType.IsGenericType() - && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>); - }); - if (mb != null) - { - createdType = createdTypeDefinition.MakeGenericType(keyItemType, valueItemType); - var method = mb.MakeGenericMethod(keyItemType, valueItemType); - parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); - return true; - } - } - } - } - - createdType = null; - parameterizedCreator = null; - return false; - } - - internal class ImmutableCollectionTypeInfo - { - public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeName, string builderTypeName) - { - ContractTypeName = contractTypeName; - CreatedTypeName = createdTypeName; - BuilderTypeName = builderTypeName; - } - - public string BuilderTypeName { get; set; } - - public string ContractTypeName { get; set; } - public string CreatedTypeName { get; set; } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JavaScriptUtils.cs deleted file mode 100644 index 0d8d4c78f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JavaScriptUtils.cs +++ /dev/null @@ -1,580 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_ASYNC -using System.Threading; -using System.Threading.Tasks; -#endif -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class BufferUtils - { - public static char[] RentBuffer(IArrayPool? bufferPool, int minSize) - { - if (bufferPool == null) return new char[minSize]; - - var buffer = bufferPool.Rent(minSize); - return buffer; - } - - public static void ReturnBuffer(IArrayPool? bufferPool, char[]? buffer) => bufferPool?.Return(buffer); - - public static char[] EnsureBufferSize(IArrayPool? bufferPool, int size, char[]? buffer) - { - if (bufferPool == null) return new char[size]; - - if (buffer != null) bufferPool.Return(buffer); - - return bufferPool.Rent(size); - } - } - - internal static class JavaScriptUtils - { - internal static readonly bool[] SingleQuoteCharEscapeFlags = new bool[128]; - internal static readonly bool[] DoubleQuoteCharEscapeFlags = new bool[128]; - internal static readonly bool[] HtmlCharEscapeFlags = new bool[128]; - - private const int UnicodeTextLength = 6; - - static JavaScriptUtils() - { - IList escapeChars = new List - { - '\n', - '\r', - '\t', - '\\', - '\f', - '\b' - }; - for (var i = 0; i < ' '; i++) escapeChars.Add((char)i); - - foreach (var escapeChar in escapeChars.Union(new[] { '\'' })) SingleQuoteCharEscapeFlags[escapeChar] = true; - foreach (var escapeChar in escapeChars.Union(new[] { '"' })) DoubleQuoteCharEscapeFlags[escapeChar] = true; - foreach (var escapeChar in escapeChars.Union(new[] { '"', '\'', '<', '>', '&' })) HtmlCharEscapeFlags[escapeChar] = true; - } - - private const string EscapedUnicodeText = "!"; - - public static bool[] GetCharEscapeFlags(StringEscapeHandling stringEscapeHandling, char quoteChar) - { - if (stringEscapeHandling == StringEscapeHandling.EscapeHtml) return HtmlCharEscapeFlags; - - if (quoteChar == '"') return DoubleQuoteCharEscapeFlags; - - return SingleQuoteCharEscapeFlags; - } - - public static bool ShouldEscapeJavaScriptString(string? s, bool[] charEscapeFlags) - { - if (s == null) return false; - - for (var i = 0; i < s.Length; i++) - { - var c = s[i]; - if (c >= charEscapeFlags.Length || charEscapeFlags[c]) return true; - } - - return false; - } - - public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, char delimiter, bool appendDelimiters, - bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool? bufferPool, ref char[]? writeBuffer - ) - { - // leading delimiter - if (appendDelimiters) writer.Write(delimiter); - - if (!StringUtils.IsNullOrEmpty(s)) - { - var lastWritePosition = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); - if (lastWritePosition == -1) - writer.Write(s); - else - { - if (lastWritePosition != 0) - { - if (writeBuffer == null || writeBuffer.Length < lastWritePosition) - writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, lastWritePosition, writeBuffer); - - // write unchanged chars at start of text. - s.CopyTo(0, writeBuffer, 0, lastWritePosition); - writer.Write(writeBuffer, 0, lastWritePosition); - } - - int length; - for (var i = lastWritePosition; i < s.Length; i++) - { - var c = s[i]; - - if (c < charEscapeFlags.Length && !charEscapeFlags[c]) continue; - - string? escapedValue; - - switch (c) - { - case '\t': - escapedValue = @"\t"; - break; - case '\n': - escapedValue = @"\n"; - break; - case '\r': - escapedValue = @"\r"; - break; - case '\f': - escapedValue = @"\f"; - break; - case '\b': - escapedValue = @"\b"; - break; - case '\\': - escapedValue = @"\\"; - break; - case '\u0085': // Next Line - escapedValue = @"\u0085"; - break; - case '\u2028': // Line Separator - escapedValue = @"\u2028"; - break; - case '\u2029': // Paragraph Separator - escapedValue = @"\u2029"; - break; - default: - if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) - { - if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) - escapedValue = @"\'"; - else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) - escapedValue = @"\"""; - else - { - if (writeBuffer == null || writeBuffer.Length < UnicodeTextLength) - writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, UnicodeTextLength, writeBuffer); - - StringUtils.ToCharAsUnicode(c, writeBuffer!); - - // slightly hacky but it saves multiple conditions in if test - escapedValue = EscapedUnicodeText; - } - } - else - escapedValue = null; - break; - } - - if (escapedValue == null) continue; - - var isEscapedUnicodeText = string.Equals(escapedValue, EscapedUnicodeText, StringComparison.Ordinal); - - if (i > lastWritePosition) - { - length = i - lastWritePosition + (isEscapedUnicodeText ? UnicodeTextLength : 0); - var start = isEscapedUnicodeText ? UnicodeTextLength : 0; - - if (writeBuffer == null || writeBuffer.Length < length) - { - var newBuffer = BufferUtils.RentBuffer(bufferPool, length); - - // the unicode text is already in the buffer - // copy it over when creating new buffer - if (isEscapedUnicodeText) - { - MiscellaneousUtils.Assert(writeBuffer != null, - "Write buffer should never be null because it is set when the escaped unicode text is encountered."); - - Array.Copy(writeBuffer, newBuffer, UnicodeTextLength); - } - - BufferUtils.ReturnBuffer(bufferPool, writeBuffer); - - writeBuffer = newBuffer; - } - - s.CopyTo(lastWritePosition, writeBuffer, start, length - start); - - // write unchanged chars before writing escaped text - writer.Write(writeBuffer, start, length - start); - } - - lastWritePosition = i + 1; - if (!isEscapedUnicodeText) - writer.Write(escapedValue); - else - writer.Write(writeBuffer, 0, UnicodeTextLength); - } - - MiscellaneousUtils.Assert(lastWritePosition != 0); - length = s.Length - lastWritePosition; - if (length > 0) - { - if (writeBuffer == null || writeBuffer.Length < length) - writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, length, writeBuffer); - - s.CopyTo(lastWritePosition, writeBuffer, 0, length); - - // write remaining text - writer.Write(writeBuffer, 0, length); - } - } - } - - // trailing delimiter - if (appendDelimiters) writer.Write(delimiter); - } - - public static string ToEscapedJavaScriptString(string? value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling - ) - { - var charEscapeFlags = GetCharEscapeFlags(stringEscapeHandling, delimiter); - - using (var w = StringUtils.CreateStringWriter(value?.Length ?? 16)) - { - char[]? buffer = null; - WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters, charEscapeFlags, stringEscapeHandling, null, ref buffer); - return w.ToString(); - } - } - - private static int FirstCharToEscape(string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling) - { - for (var i = 0; i != s.Length; i++) - { - var c = s[i]; - - if (c < charEscapeFlags.Length) - { - if (charEscapeFlags[c]) return i; - } - else if (stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) - return i; - else - { - switch (c) - { - case '\u0085': - case '\u2028': - case '\u2029': - return i; - } - } - } - - return -1; - } - -#if HAVE_ASYNC - public static Task WriteEscapedJavaScriptStringAsync(TextWriter writer, string s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken - = default) - { - if (cancellationToken.IsCancellationRequested) - { - return cancellationToken.FromCanceled(); - } - - if (appendDelimiters) - { - return WriteEscapedJavaScriptStringWithDelimitersAsync(writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - } - - if (StringUtils.IsNullOrEmpty(s)) - { - return cancellationToken.CancelIfRequestedAsync() ?? AsyncUtils.CompletedTask; - } - - return WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - } - - private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter writer, string s, char delimiter, - bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) - { - Task task = writer.WriteAsync(delimiter, cancellationToken); - if (!task.IsCompletedSucessfully()) - { - return WriteEscapedJavaScriptStringWithDelimitersAsync(task, writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - } - - if (!StringUtils.IsNullOrEmpty(s)) - { - task = - WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - if (task.IsCompletedSucessfully()) - { - return writer.WriteAsync(delimiter, cancellationToken); - } - } - - return WriteCharAsync(task, writer, delimiter, cancellationToken); - - } - - private static async Task WriteEscapedJavaScriptStringWithDelimitersAsync(Task task, TextWriter writer, string s, char delimiter, - bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - - if (!StringUtils.IsNullOrEmpty(s)) - { - await WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken).ConfigureAwait(false); - } - - await writer.WriteAsync(delimiter).ConfigureAwait(false); - } - - public static async Task WriteCharAsync(Task task, TextWriter writer, char c, CancellationToken cancellationToken) - { - await task.ConfigureAwait(false); - await writer.WriteAsync(c, cancellationToken).ConfigureAwait(false); - } - - private static Task WriteEscapedJavaScriptStringWithoutDelimitersAsync( - TextWriter writer, string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, - JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) - { - int i = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); - return i == -1 - ? writer.WriteAsync(s, cancellationToken) - : WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, i, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - } - - private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync( - TextWriter writer, string s, int lastWritePosition, bool[] charEscapeFlags, - StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, - CancellationToken cancellationToken) - { - if (writeBuffer == null || writeBuffer.Length < lastWritePosition) - { - writeBuffer = client.EnsureWriteBuffer(lastWritePosition, UnicodeTextLength); - } - - if (lastWritePosition != 0) - { - s.CopyTo(0, writeBuffer, 0, lastWritePosition); - - // write unchanged chars at start of text. - await writer.WriteAsync(writeBuffer, 0, lastWritePosition, cancellationToken).ConfigureAwait(false); - } - - int length; - bool isEscapedUnicodeText = false; - string? escapedValue = null; - - for (int i = lastWritePosition; i < s.Length; i++) - { - char c = s[i]; - - if (c < charEscapeFlags.Length && !charEscapeFlags[c]) - { - continue; - } - - switch (c) - { - case '\t': - escapedValue = @"\t"; - break; - case '\n': - escapedValue = @"\n"; - break; - case '\r': - escapedValue = @"\r"; - break; - case '\f': - escapedValue = @"\f"; - break; - case '\b': - escapedValue = @"\b"; - break; - case '\\': - escapedValue = @"\\"; - break; - case '\u0085': // Next Line - escapedValue = @"\u0085"; - break; - case '\u2028': // Line Separator - escapedValue = @"\u2028"; - break; - case '\u2029': // Paragraph Separator - escapedValue = @"\u2029"; - break; - default: - if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) - { - if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) - { - escapedValue = @"\'"; - } - else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) - { - escapedValue = @"\"""; - } - else - { - if (writeBuffer.Length < UnicodeTextLength) - { - writeBuffer = client.EnsureWriteBuffer(UnicodeTextLength, 0); - } - - StringUtils.ToCharAsUnicode(c, writeBuffer); - - isEscapedUnicodeText = true; - } - } - else - { - continue; - } - break; - } - - if (i > lastWritePosition) - { - length = i - lastWritePosition + (isEscapedUnicodeText ? UnicodeTextLength : 0); - int start = isEscapedUnicodeText ? UnicodeTextLength : 0; - - if (writeBuffer.Length < length) - { - writeBuffer = client.EnsureWriteBuffer(length, UnicodeTextLength); - } - - s.CopyTo(lastWritePosition, writeBuffer, start, length - start); - - // write unchanged chars before writing escaped text - await writer.WriteAsync(writeBuffer, start, length - start, cancellationToken).ConfigureAwait(false); - } - - lastWritePosition = i + 1; - if (!isEscapedUnicodeText) - { - await writer.WriteAsync(escapedValue!, cancellationToken).ConfigureAwait(false); - } - else - { - await writer.WriteAsync(writeBuffer, 0, UnicodeTextLength, cancellationToken).ConfigureAwait(false); - isEscapedUnicodeText = false; - } - } - - length = s.Length - lastWritePosition; - - if (length != 0) - { - if (writeBuffer.Length < length) - { - writeBuffer = client.EnsureWriteBuffer(length, 0); - } - - s.CopyTo(lastWritePosition, writeBuffer, 0, length); - - // write remaining text - await writer.WriteAsync(writeBuffer, 0, length, cancellationToken).ConfigureAwait(false); - } - } -#endif - - public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, [NotNullWhen(false)] out string? errorMessage) - { - dateTime = default; - errorMessage = null; - - if (!TryGetDateConstructorValue(reader, out var t1, out errorMessage) || t1 == null) - { - errorMessage = errorMessage ?? "Date constructor has no arguments."; - return false; - } - if (!TryGetDateConstructorValue(reader, out var t2, out errorMessage)) - return false; - - if (t2 != null) - { - // Only create a list when there is more than one argument - var dateArgs = new List { t1.Value, t2.Value }; - while (true) - { - if (!TryGetDateConstructorValue(reader, out var integer, out errorMessage)) - return false; - - if (integer != null) - dateArgs.Add(integer.Value); - else - break; - } - - if (dateArgs.Count > 7) - { - errorMessage = "Unexpected number of arguments when reading date constructor."; - return false; - } - - // Pad args out to the number used by the ctor - while (dateArgs.Count < 7) dateArgs.Add(0); - - dateTime = new DateTime((int)dateArgs[0], (int)dateArgs[1] + 1, dateArgs[2] == 0 ? 1 : (int)dateArgs[2], - (int)dateArgs[3], (int)dateArgs[4], (int)dateArgs[5], (int)dateArgs[6]); - } - else - dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(t1.Value); - - return true; - } - - private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, [NotNullWhen(false)] out string? errorMessage) - { - integer = null; - errorMessage = null; - - if (!reader.Read()) - { - errorMessage = "Unexpected end when reading date constructor."; - return false; - } - if (reader.TokenType == JsonToken.EndConstructor) return true; - - if (reader.TokenType != JsonToken.Integer) - { - errorMessage = "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType; - return false; - } - - integer = (long)reader.Value!; - return true; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JsonTokenUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JsonTokenUtils.cs deleted file mode 100644 index a0e5310ec..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/JsonTokenUtils.cs +++ /dev/null @@ -1,77 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class JsonTokenUtils - { - internal static bool IsEndToken(JsonToken token) - { - switch (token) - { - case JsonToken.EndObject: - case JsonToken.EndArray: - case JsonToken.EndConstructor: - return true; - default: - return false; - } - } - - internal static bool IsStartToken(JsonToken token) - { - switch (token) - { - case JsonToken.StartObject: - case JsonToken.StartArray: - case JsonToken.StartConstructor: - return true; - default: - return false; - } - } - - internal static bool IsPrimitiveToken(JsonToken token) - { - switch (token) - { - case JsonToken.Integer: - case JsonToken.Float: - case JsonToken.String: - case JsonToken.Boolean: - case JsonToken.Undefined: - case JsonToken.Null: - case JsonToken.Date: - case JsonToken.Bytes: - return true; - default: - return false; - } - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs deleted file mode 100644 index e1bc46d79..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs +++ /dev/null @@ -1,107 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#if !HAVE_LINQ - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class LateBoundReflectionDelegateFactory : ReflectionDelegateFactory - { - private static readonly LateBoundReflectionDelegateFactory _instance = new(); - - internal static ReflectionDelegateFactory Instance => _instance; - - public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) - { - ValidationUtils.ArgumentNotNull(method, nameof(method)); - - if (method is ConstructorInfo c) - { - // don't convert to method group to avoid medium trust issues - // https://github.com/JamesNK/Newtonsoft.Json/issues/476 - return a => c.Invoke(a); - } - - return a => method.Invoke(null, a); - } - - public override MethodCall CreateMethodCall(MethodBase method) - { - ValidationUtils.ArgumentNotNull(method, nameof(method)); - - if (method is ConstructorInfo c) return (o, a) => c.Invoke(a); - - return (o, a) => method.Invoke(o, a); - } - - public override Func CreateDefaultConstructor(Type type) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - - if (type.IsValueType()) return () => (T)Activator.CreateInstance(type); - - var constructorInfo = ReflectionUtils.GetDefaultConstructor(type, true); - - return () => (T)constructorInfo.Invoke(null); - } - - public override Func CreateGet(PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - return o => propertyInfo.GetValue(o, null); - } - - public override Func CreateGet(FieldInfo fieldInfo) - { - ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); - - return o => fieldInfo.GetValue(o); - } - - public override Action CreateSet(FieldInfo fieldInfo) - { - ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); - - return (o, v) => fieldInfo.SetValue(o, v); - } - - public override Action CreateSet(PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - return (o, v) => propertyInfo.SetValue(o, v, null); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LinqBridge.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LinqBridge.cs deleted file mode 100644 index 319fbfb39..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/LinqBridge.cs +++ /dev/null @@ -1,2903 +0,0 @@ -#if !HAVE_LINQ - -#region License, Terms and Author(s) - -// -// LINQBridge -// Copyright (c) 2007-9 Atif Aziz, Joseph Albahari. All rights reserved. -// -// Author(s): -// -// Atif Aziz, http://www.raboof.com -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the New BSD License, a copy of which should have -// been delivered along with this distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; - -#nullable disable - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge -{ - /// - /// Provides a set of static (Shared in Visual Basic) methods for - /// querying objects that implement . - /// - internal static partial class Enumerable - { - private static class Futures - { - public static readonly Func Default = () => default; - public static readonly Func Undefined = () => { throw new InvalidOperationException(); }; - } - - private static class Sequence - { - public static readonly IEnumerable Empty = new T[0]; - } - - /// - /// Returns the input typed as . - /// - public static IEnumerable AsEnumerable(IEnumerable source) => source; - - /// - /// Returns an empty that has the - /// specified type argument. - /// - public static IEnumerable Empty() => Sequence.Empty; - - /// - /// Converts the elements of an to the - /// specified type. - /// - public static IEnumerable Cast( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - var servesItself = source as IEnumerable; - if (servesItself != null - && (!(servesItself is TResult[]) || servesItself.GetType().GetElementType() == typeof(TResult))) - return servesItself; - - return CastYield(source); - } - - private static IEnumerable CastYield( - IEnumerable source - ) - { - foreach (var item in source) - yield return (TResult)item; - } - - /// - /// Filters the elements of an based on a specified type. - /// - public static IEnumerable OfType( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return OfTypeYield(source); - } - - private static IEnumerable OfTypeYield( - IEnumerable source - ) - { - foreach (var item in source) - { - if (item is TResult) - yield return (TResult)item; - } - } - - /// - /// Generates a sequence of integral numbers within a specified range. - /// - /// The value of the first integer in the sequence. - /// The number of sequential integers to generate. - public static IEnumerable Range(int start, int count) - { - if (count < 0) - throw new ArgumentOutOfRangeException("count", count, null); - - var end = (long)start + count; - if (end - 1 >= int.MaxValue) - throw new ArgumentOutOfRangeException("count", count, null); - - return RangeYield(start, end); - } - - private static IEnumerable RangeYield(int start, long end) - { - for (var i = start; i < end; i++) - yield return i; - } - - /// - /// Generates a sequence that contains one repeated value. - /// - public static IEnumerable Repeat(TResult element, int count) - { - if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); - - return RepeatYield(element, count); - } - - private static IEnumerable RepeatYield(TResult element, int count) - { - for (var i = 0; i < count; i++) - yield return element; - } - - /// - /// Filters a sequence of values based on a predicate. - /// - public static IEnumerable Where( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(source, "source"); - CheckNotNull(predicate, "predicate"); - - return WhereYield(source, predicate); - } - - private static IEnumerable WhereYield( - IEnumerable source, - Func predicate - ) - { - foreach (var item in source) - { - if (predicate(item)) - yield return item; - } - } - - /// - /// Filters a sequence of values based on a predicate. - /// Each element's index is used in the logic of the predicate function. - /// - public static IEnumerable Where( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(source, "source"); - CheckNotNull(predicate, "predicate"); - - return WhereYield(source, predicate); - } - - private static IEnumerable WhereYield( - IEnumerable source, - Func predicate - ) - { - var i = 0; - foreach (var item in source) - { - if (predicate(item, i++)) - yield return item; - } - } - - /// - /// Projects each element of a sequence into a new form. - /// - public static IEnumerable Select( - this IEnumerable source, - Func selector - ) - { - CheckNotNull(source, "source"); - CheckNotNull(selector, "selector"); - - return SelectYield(source, selector); - } - - private static IEnumerable SelectYield( - IEnumerable source, - Func selector - ) - { - foreach (var item in source) - yield return selector(item); - } - - /// - /// Projects each element of a sequence into a new form by - /// incorporating the element's index. - /// - public static IEnumerable Select( - this IEnumerable source, - Func selector - ) - { - CheckNotNull(source, "source"); - CheckNotNull(selector, "selector"); - - return SelectYield(source, selector); - } - - private static IEnumerable SelectYield( - IEnumerable source, - Func selector - ) - { - var i = 0; - foreach (var item in source) - yield return selector(item, i++); - } - - /// - /// Projects each element of a sequence to an - /// and flattens the resulting sequences into one sequence. - /// - public static IEnumerable SelectMany( - this IEnumerable source, - Func> selector - ) - { - CheckNotNull(selector, "selector"); - - return source.SelectMany((item, i) => selector(item)); - } - - /// - /// Projects each element of a sequence to an , - /// and flattens the resulting sequences into one sequence. The - /// index of each source element is used in the projected form of - /// that element. - /// - public static IEnumerable SelectMany( - this IEnumerable source, - Func> selector - ) - { - CheckNotNull(selector, "selector"); - - return source.SelectMany(selector, (item, subitem) => subitem); - } - - /// - /// Projects each element of a sequence to an , - /// flattens the resulting sequences into one sequence, and invokes - /// a result selector function on each element therein. - /// - public static IEnumerable SelectMany( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector - ) - { - CheckNotNull(collectionSelector, "collectionSelector"); - - return source.SelectMany((item, i) => collectionSelector(item), resultSelector); - } - - /// - /// Projects each element of a sequence to an , - /// flattens the resulting sequences into one sequence, and invokes - /// a result selector function on each element therein. The index of - /// each source element is used in the intermediate projected form - /// of that element. - /// - public static IEnumerable SelectMany( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector - ) - { - CheckNotNull(source, "source"); - CheckNotNull(collectionSelector, "collectionSelector"); - CheckNotNull(resultSelector, "resultSelector"); - - return SelectManyYield(source, collectionSelector, resultSelector); - } - - private static IEnumerable SelectManyYield( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector - ) - { - var i = 0; - foreach (var item in source) - foreach (var subitem in collectionSelector(item, i++)) - yield return resultSelector(item, subitem); - } - - /// - /// Returns elements from a sequence as long as a specified condition is true. - /// - public static IEnumerable TakeWhile( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(predicate, "predicate"); - - return source.TakeWhile((item, i) => predicate(item)); - } - - /// - /// Returns elements from a sequence as long as a specified condition is true. - /// The element's index is used in the logic of the predicate function. - /// - public static IEnumerable TakeWhile( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(source, "source"); - CheckNotNull(predicate, "predicate"); - - return TakeWhileYield(source, predicate); - } - - private static IEnumerable TakeWhileYield( - this IEnumerable source, - Func predicate - ) - { - var i = 0; - foreach (var item in source) - { - if (predicate(item, i++)) - yield return item; - else - break; - } - } - - /// - /// Base implementation of First operator. - /// - private static TSource FirstImpl( - this IEnumerable source, - Func empty - ) - { - CheckNotNull(source, "source"); - MiscellaneousUtils.Assert(empty != null); - - var list = source as IList; // optimized case for lists - if (list != null) - return list.Count > 0 ? list[0] : empty(); - - using (var e = source.GetEnumerator()) // fallback for enumeration - return e.MoveNext() ? e.Current : empty(); - } - - /// - /// Returns the first element of a sequence. - /// - public static TSource First( - this IEnumerable source - ) => - source.FirstImpl(Futures.Undefined); - - /// - /// Returns the first element in a sequence that satisfies a specified condition. - /// - public static TSource First( - this IEnumerable source, - Func predicate - ) => - First(source.Where(predicate)); - - /// - /// Returns the first element of a sequence, or a default value if - /// the sequence contains no elements. - /// - public static TSource FirstOrDefault( - this IEnumerable source - ) => - source.FirstImpl(Futures.Default); - - /// - /// Returns the first element of the sequence that satisfies a - /// condition or a default value if no such element is found. - /// - public static TSource FirstOrDefault( - this IEnumerable source, - Func predicate - ) => - FirstOrDefault(source.Where(predicate)); - - /// - /// Base implementation of Last operator. - /// - private static TSource LastImpl( - this IEnumerable source, - Func empty - ) - { - CheckNotNull(source, "source"); - - var list = source as IList; // optimized case for lists - if (list != null) - return list.Count > 0 ? list[list.Count - 1] : empty(); - - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - return empty(); - - var last = e.Current; - while (e.MoveNext()) - last = e.Current; - - return last; - } - } - - /// - /// Returns the last element of a sequence. - /// - public static TSource Last( - this IEnumerable source - ) => - source.LastImpl(Futures.Undefined); - - /// - /// Returns the last element of a sequence that satisfies a - /// specified condition. - /// - public static TSource Last( - this IEnumerable source, - Func predicate - ) => - Last(source.Where(predicate)); - - /// - /// Returns the last element of a sequence, or a default value if - /// the sequence contains no elements. - /// - public static TSource LastOrDefault( - this IEnumerable source - ) => - source.LastImpl(Futures.Default); - - /// - /// Returns the last element of a sequence that satisfies a - /// condition or a default value if no such element is found. - /// - public static TSource LastOrDefault( - this IEnumerable source, - Func predicate - ) => - LastOrDefault(source.Where(predicate)); - - /// - /// Base implementation of Single operator. - /// - private static TSource SingleImpl( - this IEnumerable source, - Func empty - ) - { - CheckNotNull(source, "source"); - - using (var e = source.GetEnumerator()) - { - if (e.MoveNext()) - { - var single = e.Current; - if (!e.MoveNext()) - return single; - - throw new InvalidOperationException(); - } - - return empty(); - } - } - - /// - /// Returns the only element of a sequence, and throws an exception - /// if there is not exactly one element in the sequence. - /// - public static TSource Single( - this IEnumerable source - ) => - source.SingleImpl(Futures.Undefined); - - /// - /// Returns the only element of a sequence that satisfies a - /// specified condition, and throws an exception if more than one - /// such element exists. - /// - public static TSource Single( - this IEnumerable source, - Func predicate - ) => - Single(source.Where(predicate)); - - /// - /// Returns the only element of a sequence, or a default value if - /// the sequence is empty; this method throws an exception if there - /// is more than one element in the sequence. - /// - public static TSource SingleOrDefault( - this IEnumerable source - ) => - source.SingleImpl(Futures.Default); - - /// - /// Returns the only element of a sequence that satisfies a - /// specified condition or a default value if no such element - /// exists; this method throws an exception if more than one element - /// satisfies the condition. - /// - public static TSource SingleOrDefault( - this IEnumerable source, - Func predicate - ) => - SingleOrDefault(source.Where(predicate)); - - /// - /// Returns the element at a specified index in a sequence. - /// - public static TSource ElementAt( - this IEnumerable source, - int index - ) - { - CheckNotNull(source, "source"); - - if (index < 0) - throw new ArgumentOutOfRangeException("index", index, null); - - var list = source as IList; - if (list != null) - return list[index]; - - try - { - return source.SkipWhile((item, i) => i < index).First(); - } - catch (InvalidOperationException) // if thrown by First - { - throw new ArgumentOutOfRangeException("index", index, null); - } - } - - /// - /// Returns the element at a specified index in a sequence or a - /// default value if the index is out of range. - /// - public static TSource ElementAtOrDefault( - this IEnumerable source, - int index - ) - { - CheckNotNull(source, "source"); - - if (index < 0) - return default; - - var list = source as IList; - if (list != null) - return index < list.Count ? list[index] : default; - - return source.SkipWhile((item, i) => i < index).FirstOrDefault(); - } - - /// - /// Inverts the order of the elements in a sequence. - /// - public static IEnumerable Reverse( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return ReverseYield(source); - } - - private static IEnumerable ReverseYield(IEnumerable source) - { - var stack = new Stack(source); - - foreach (var item in stack) - yield return item; - } - - /// - /// Returns a specified number of contiguous elements from the start - /// of a sequence. - /// - public static IEnumerable Take( - this IEnumerable source, - int count - ) => - source.Where((item, i) => i < count); - - /// - /// Bypasses a specified number of elements in a sequence and then - /// returns the remaining elements. - /// - public static IEnumerable Skip( - this IEnumerable source, - int count - ) => - source.Where((item, i) => i >= count); - - /// - /// Bypasses elements in a sequence as long as a specified condition - /// is true and then returns the remaining elements. - /// - public static IEnumerable SkipWhile( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(predicate, "predicate"); - - return source.SkipWhile((item, i) => predicate(item)); - } - - /// - /// Bypasses elements in a sequence as long as a specified condition - /// is true and then returns the remaining elements. The element's - /// index is used in the logic of the predicate function. - /// - public static IEnumerable SkipWhile( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(source, "source"); - CheckNotNull(predicate, "predicate"); - - return SkipWhileYield(source, predicate); - } - - private static IEnumerable SkipWhileYield( - IEnumerable source, - Func predicate - ) - { - using (var e = source.GetEnumerator()) - { - for (var i = 0;; i++) - { - if (!e.MoveNext()) - yield break; - - if (!predicate(e.Current, i)) - break; - } - - do - yield return e.Current; - while (e.MoveNext()); - } - } - - /// - /// Returns the number of elements in a sequence. - /// - public static int Count( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - var collection = source as ICollection; - if (collection != null) return collection.Count; - - using (var en = source.GetEnumerator()) - { - var count = 0; - while (en.MoveNext()) ++count; - - return count; - } - } - - /// - /// Returns a number that represents how many elements in the - /// specified sequence satisfy a condition. - /// - public static int Count( - this IEnumerable source, - Func predicate - ) => - Count(source.Where(predicate)); - - /// - /// Returns a that represents the total number - /// of elements in a sequence. - /// - public static long LongCount( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - var array = source as Array; - return array != null - ? array.LongLength - : source.Aggregate(0L, (count, item) => count + 1); - } - - /// - /// Returns a that represents how many elements - /// in a sequence satisfy a condition. - /// - public static long LongCount( - this IEnumerable source, - Func predicate - ) => - LongCount(source.Where(predicate)); - - /// - /// Concatenates two sequences. - /// - public static IEnumerable Concat( - this IEnumerable first, - IEnumerable second - ) - { - CheckNotNull(first, "first"); - CheckNotNull(second, "second"); - - return ConcatYield(first, second); - } - - private static IEnumerable ConcatYield( - IEnumerable first, - IEnumerable second - ) - { - foreach (var item in first) - yield return item; - - foreach (var item in second) - yield return item; - } - - /// - /// Creates a from an . - /// - public static List ToList( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return new List(source); - } - - /// - /// Creates an array from an . - /// - public static TSource[] ToArray( - this IEnumerable source - ) - { - var ilist = source as IList; - if (ilist != null) - { - var array = new TSource[ilist.Count]; - ilist.CopyTo(array, 0); - return array; - } - - return source.ToList().ToArray(); - } - - /// - /// Returns distinct elements from a sequence by using the default - /// equality comparer to compare values. - /// - public static IEnumerable Distinct( - this IEnumerable source - ) => - Distinct(source, /* comparer */ null); - - /// - /// Returns distinct elements from a sequence by using a specified - /// to compare values. - /// - public static IEnumerable Distinct( - this IEnumerable source, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - - return DistinctYield(source, comparer); - } - - private static IEnumerable DistinctYield( - IEnumerable source, - IEqualityComparer comparer - ) - { - var set = new Dictionary(comparer); - var gotNull = false; - - foreach (var item in source) - { - if (item == null) - { - if (gotNull) - continue; - - gotNull = true; - } - else - { - if (set.ContainsKey(item)) - continue; - - set.Add(item, null); - } - - yield return item; - } - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function. - /// - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector - ) => - ToLookup(source, keySelector, e => e, /* comparer */ null); - - /// - /// Creates a from an - /// according to a specified key - /// selector function and a key comparer. - /// - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer - ) => - ToLookup(source, keySelector, e => e, comparer); - - /// - /// Creates a from an - /// according to specified key - /// and element selector functions. - /// - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - Func elementSelector - ) => - ToLookup(source, keySelector, elementSelector, /* comparer */ null); - - /// - /// Creates a from an - /// according to a specified key - /// selector function, a comparer and an element selector function. - /// - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - CheckNotNull(elementSelector, "elementSelector"); - - var lookup = new Lookup(comparer); - - foreach (var item in source) - { - var key = keySelector(item); - - var grouping = (Grouping)lookup.Find(key); - if (grouping == null) - { - grouping = new Grouping(key); - lookup.Add(grouping); - } - - grouping.Add(elementSelector(item)); - } - - return lookup; - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function. - /// - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector - ) => - GroupBy(source, keySelector, /* comparer */ null); - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and compares the keys by using a specified - /// comparer. - /// - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer - ) => - GroupBy(source, keySelector, e => e, comparer); - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and projects the elements for each group by - /// using a specified function. - /// - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector - ) => - GroupBy(source, keySelector, elementSelector, /* comparer */ null); - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. - /// - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - CheckNotNull(elementSelector, "elementSelector"); - - return ToLookup(source, keySelector, elementSelector, comparer); - } - - /// - /// Groups the elements of a sequence according to a key selector - /// function. The keys are compared by using a comparer and each - /// group's elements are projected by using a specified function. - /// - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func, TResult> resultSelector - ) => - GroupBy(source, keySelector, resultSelector, /* comparer */ null); - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. The elements of each group are projected by using a - /// specified function. - /// - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func, TResult> resultSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - CheckNotNull(resultSelector, "resultSelector"); - - return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g)); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. The keys are compared by using a specified comparer. - /// - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - Func, TResult> resultSelector - ) => - GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null); - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. Key values are compared by using a specified comparer, - /// and the elements of each group are projected by using a - /// specified function. - /// - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - Func, TResult> resultSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - CheckNotNull(elementSelector, "elementSelector"); - CheckNotNull(resultSelector, "resultSelector"); - - return ToLookup(source, keySelector, elementSelector, comparer) - .Select(g => resultSelector(g.Key, g)); - } - - /// - /// Applies an accumulator function over a sequence. - /// - public static TSource Aggregate( - this IEnumerable source, - Func func - ) - { - CheckNotNull(source, "source"); - CheckNotNull(func, "func"); - - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - throw new InvalidOperationException(); - - return e.Renumerable().Skip(1).Aggregate(e.Current, func); - } - } - - /// - /// Applies an accumulator function over a sequence. The specified - /// seed value is used as the initial accumulator value. - /// - public static TAccumulate Aggregate( - this IEnumerable source, - TAccumulate seed, - Func func - ) => - Aggregate(source, seed, func, r => r); - - /// - /// Applies an accumulator function over a sequence. The specified - /// seed value is used as the initial accumulator value, and the - /// specified function is used to select the result value. - /// - public static TResult Aggregate( - this IEnumerable source, - TAccumulate seed, - Func func, - Func resultSelector - ) - { - CheckNotNull(source, "source"); - CheckNotNull(func, "func"); - CheckNotNull(resultSelector, "resultSelector"); - - var result = seed; - - foreach (var item in source) - result = func(result, item); - - return resultSelector(result); - } - - /// - /// Produces the set union of two sequences by using the default - /// equality comparer. - /// - public static IEnumerable Union( - this IEnumerable first, - IEnumerable second - ) => - Union(first, second, /* comparer */ null); - - /// - /// Produces the set union of two sequences by using a specified - /// . - /// - public static IEnumerable Union( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer - ) => - first.Concat(second).Distinct(comparer); - - /// - /// Returns the elements of the specified sequence or the type - /// parameter's default value in a singleton collection if the - /// sequence is empty. - /// - public static IEnumerable DefaultIfEmpty( - this IEnumerable source - ) => - source.DefaultIfEmpty(default); - - /// - /// Returns the elements of the specified sequence or the specified - /// value in a singleton collection if the sequence is empty. - /// - public static IEnumerable DefaultIfEmpty( - this IEnumerable source, - TSource defaultValue - ) - { - CheckNotNull(source, "source"); - - return DefaultIfEmptyYield(source, defaultValue); - } - - private static IEnumerable DefaultIfEmptyYield( - IEnumerable source, - TSource defaultValue - ) - { - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - yield return defaultValue; - else - { - do - yield return e.Current; - while (e.MoveNext()); - } - } - } - - /// - /// Determines whether all elements of a sequence satisfy a condition. - /// - public static bool All( - this IEnumerable source, - Func predicate - ) - { - CheckNotNull(source, "source"); - CheckNotNull(predicate, "predicate"); - - foreach (var item in source) - { - if (!predicate(item)) - return false; - } - - return true; - } - - /// - /// Determines whether a sequence contains any elements. - /// - public static bool Any( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - using (var e = source.GetEnumerator()) - return e.MoveNext(); - } - - /// - /// Determines whether any element of a sequence satisfies a - /// condition. - /// - public static bool Any( - this IEnumerable source, - Func predicate - ) - { - foreach (var item in source) - { - if (predicate(item)) - return true; - } - - return false; - } - - /// - /// Determines whether a sequence contains a specified element by - /// using the default equality comparer. - /// - public static bool Contains( - this IEnumerable source, - TSource value - ) => - source.Contains(value, /* comparer */ null); - - /// - /// Determines whether a sequence contains a specified element by - /// using a specified . - /// - public static bool Contains( - this IEnumerable source, - TSource value, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - - if (comparer == null) - { - var collection = source as ICollection; - if (collection != null) - return collection.Contains(value); - } - - comparer = comparer ?? EqualityComparer.Default; - return source.Any(item => comparer.Equals(item, value)); - } - - /// - /// Determines whether two sequences are equal by comparing the - /// elements by using the default equality comparer for their type. - /// - public static bool SequenceEqual( - this IEnumerable first, - IEnumerable second - ) => - first.SequenceEqual(second, /* comparer */ null); - - /// - /// Determines whether two sequences are equal by comparing their - /// elements by using a specified . - /// - public static bool SequenceEqual( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer - ) - { - CheckNotNull(first, "first"); - CheckNotNull(second, "second"); - - comparer = comparer ?? EqualityComparer.Default; - - using (IEnumerator lhs = first.GetEnumerator(), - rhs = second.GetEnumerator()) - { - do - { - if (!lhs.MoveNext()) - return !rhs.MoveNext(); - - if (!rhs.MoveNext()) - return false; - } while (comparer.Equals(lhs.Current, rhs.Current)); - } - - return false; - } - - /// - /// Base implementation for Min/Max operator. - /// - private static TSource MinMaxImpl( - this IEnumerable source, - Func lesser - ) - { - CheckNotNull(source, "source"); - MiscellaneousUtils.Assert(lesser != null); - - return source.Aggregate((a, item) => lesser(a, item) ? a : item); - } - - /// - /// Base implementation for Min/Max operator for nullable types. - /// - private static TSource? MinMaxImpl( - this IEnumerable source, - TSource? seed, Func lesser - ) where TSource : struct - { - CheckNotNull(source, "source"); - MiscellaneousUtils.Assert(lesser != null); - - return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item); - - // == MinMaxImpl(Repeat(null, 1).Concat(source), lesser); - } - - /// - /// Returns the minimum value in a generic sequence. - /// - public static TSource Min( - this IEnumerable source - ) - { - var comparer = Comparer.Default; - return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0); - } - - /// - /// Invokes a transform function on each element of a generic - /// sequence and returns the minimum resulting value. - /// - public static TResult Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a generic sequence. - /// - public static TSource Max( - this IEnumerable source - ) - { - var comparer = Comparer.Default; - return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0); - } - - /// - /// Invokes a transform function on each element of a generic - /// sequence and returns the maximum resulting value. - /// - public static TResult Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - - /// - /// Makes an enumerator seen as enumerable once more. - /// - /// - /// The supplied enumerator must have been started. The first element - /// returned is the element the enumerator was on when passed in. - /// DO NOT use this method if the caller must be a generator. It is - /// mostly safe among aggregate operations. - /// - private static IEnumerable Renumerable(this IEnumerator e) - { - MiscellaneousUtils.Assert(e != null); - - do - yield return e.Current; - while (e.MoveNext()); - } - - /// - /// Sorts the elements of a sequence in ascending order according to a key. - /// - public static IOrderedEnumerable OrderBy( - this IEnumerable source, - Func keySelector - ) => - source.OrderBy(keySelector, /* comparer */ null); - - /// - /// Sorts the elements of a sequence in ascending order by using a - /// specified comparer. - /// - public static IOrderedEnumerable OrderBy( - this IEnumerable source, - Func keySelector, - IComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - - return new OrderedEnumerable(source, keySelector, comparer, /* descending */ false); - } - - /// - /// Sorts the elements of a sequence in descending order according to a key. - /// - public static IOrderedEnumerable OrderByDescending( - this IEnumerable source, - Func keySelector - ) => - source.OrderByDescending(keySelector, /* comparer */ null); - - /// - /// Sorts the elements of a sequence in descending order by using a - /// specified comparer. - /// - public static IOrderedEnumerable OrderByDescending( - this IEnumerable source, - Func keySelector, - IComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(source, "keySelector"); - - return new OrderedEnumerable(source, keySelector, comparer, /* descending */ true); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// ascending order according to a key. - /// - public static IOrderedEnumerable ThenBy( - this IOrderedEnumerable source, - Func keySelector - ) => - source.ThenBy(keySelector, /* comparer */ null); - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// ascending order by using a specified comparer. - /// - public static IOrderedEnumerable ThenBy( - this IOrderedEnumerable source, - Func keySelector, - IComparer comparer - ) - { - CheckNotNull(source, "source"); - - return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// descending order, according to a key. - /// - public static IOrderedEnumerable ThenByDescending( - this IOrderedEnumerable source, - Func keySelector - ) => - source.ThenByDescending(keySelector, /* comparer */ null); - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// descending order by using a specified comparer. - /// - public static IOrderedEnumerable ThenByDescending( - this IOrderedEnumerable source, - Func keySelector, - IComparer comparer - ) - { - CheckNotNull(source, "source"); - - return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true); - } - - /// - /// Base implementation for Intersect and Except operators. - /// - private static IEnumerable IntersectExceptImpl( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer, - bool flag - ) - { - CheckNotNull(first, "first"); - CheckNotNull(second, "second"); - - var keys = new List(); - var flags = new Dictionary(comparer); - - foreach (var item in first.Where(k => !flags.ContainsKey(k))) - { - flags.Add(item, !flag); - keys.Add(item); - } - - foreach (var item in second.Where(flags.ContainsKey)) - flags[item] = flag; - - // - // As per docs, "the marked elements are yielded in the order in - // which they were collected. - // - - return keys.Where(item => flags[item]); - } - - /// - /// Produces the set intersection of two sequences by using the - /// default equality comparer to compare values. - /// - public static IEnumerable Intersect( - this IEnumerable first, - IEnumerable second - ) => - first.Intersect(second, /* comparer */ null); - - /// - /// Produces the set intersection of two sequences by using the - /// specified to compare values. - /// - public static IEnumerable Intersect( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer - ) => - IntersectExceptImpl(first, second, comparer, /* flag */ true); - - /// - /// Produces the set difference of two sequences by using the - /// default equality comparer to compare values. - /// - public static IEnumerable Except( - this IEnumerable first, - IEnumerable second - ) => - first.Except(second, /* comparer */ null); - - /// - /// Produces the set difference of two sequences by using the - /// specified to compare values. - /// - public static IEnumerable Except( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer - ) => - IntersectExceptImpl(first, second, comparer, /* flag */ false); - - /// - /// Creates a from an - /// according to a specified key - /// selector function. - /// - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector - ) => - source.ToDictionary(keySelector, /* comparer */ null); - - /// - /// Creates a from an - /// according to a specified key - /// selector function and key comparer. - /// - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer - ) => - source.ToDictionary(keySelector, e => e); - - /// - /// Creates a from an - /// according to specified key - /// selector and element selector functions. - /// - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - Func elementSelector - ) => - source.ToDictionary(keySelector, elementSelector, /* comparer */ null); - - /// - /// Creates a from an - /// according to a specified key - /// selector function, a comparer, and an element selector function. - /// - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(source, "source"); - CheckNotNull(keySelector, "keySelector"); - CheckNotNull(elementSelector, "elementSelector"); - - var dict = new Dictionary(comparer); - - foreach (var item in source) - // - // ToDictionary is meant to throw ArgumentNullException if - // keySelector produces a key that is null and - // Argument exception if keySelector produces duplicate keys - // for two elements. Incidentally, the documentation for - // IDictionary.Add says that the Add method - // throws the same exceptions under the same circumstances - // so we don't need to do any additional checking or work - // here and let the Add implementation do all the heavy - // lifting. - // - - dict.Add(keySelector(item), elementSelector(item)); - - return dict; - } - - /// - /// Correlates the elements of two sequences based on matching keys. - /// The default equality comparer is used to compare keys. - /// - public static IEnumerable Join( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func resultSelector - ) => - outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); - - /// - /// Correlates the elements of two sequences based on matching keys. - /// The default equality comparer is used to compare keys. A - /// specified is used to compare keys. - /// - public static IEnumerable Join( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func resultSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(outer, "outer"); - CheckNotNull(inner, "inner"); - CheckNotNull(outerKeySelector, "outerKeySelector"); - CheckNotNull(innerKeySelector, "innerKeySelector"); - CheckNotNull(resultSelector, "resultSelector"); - - var lookup = inner.ToLookup(innerKeySelector, comparer); - - return - from o in outer - from i in lookup[outerKeySelector(o)] - select resultSelector(o, i); - } - - /// - /// Correlates the elements of two sequences based on equality of - /// keys and groups the results. The default equality comparer is - /// used to compare keys. - /// - public static IEnumerable GroupJoin( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func, TResult> resultSelector - ) => - outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); - - /// - /// Correlates the elements of two sequences based on equality of - /// keys and groups the results. The default equality comparer is - /// used to compare keys. A specified - /// is used to compare keys. - /// - public static IEnumerable GroupJoin( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func, TResult> resultSelector, - IEqualityComparer comparer - ) - { - CheckNotNull(outer, "outer"); - CheckNotNull(inner, "inner"); - CheckNotNull(outerKeySelector, "outerKeySelector"); - CheckNotNull(innerKeySelector, "innerKeySelector"); - CheckNotNull(resultSelector, "resultSelector"); - - var lookup = inner.ToLookup(innerKeySelector, comparer); - return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)])); - } - - [DebuggerStepThrough] - private static void CheckNotNull(T value, string name) where T : class - { - if (value == null) - throw new ArgumentNullException(name); - } - - private sealed class Grouping : List, IGrouping - { - internal Grouping(K key) => Key = key; - - public K Key { get; } - } - } - - internal partial class Enumerable - { - /// - /// Computes the sum of a sequence of values. - /// - public static int Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - var sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static int Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of values. - /// - public static double Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - long count = 0; - - foreach (var num in source) - { - checked - { - sum += num; - count++; - } - } - - if (count == 0) - throw new InvalidOperationException(); - - return (double)sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static int? Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - var sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static int? Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of nullable values. - /// - public static double? Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - { - checked - { - sum += (int)num; - count++; - } - } - - if (count == 0) - return null; - - return (double?)sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double? Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - public static int? Min( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - public static int? Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - public static int? Max( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || max != null && x.Value < max.Value); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - public static int? Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - - /// - /// Computes the sum of a sequence of values. - /// - public static long Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static long Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of values. - /// - public static double Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - long count = 0; - - foreach (var num in source) - { - checked - { - sum += num; - count++; - } - } - - if (count == 0) - throw new InvalidOperationException(); - - return (double)sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static long? Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static long? Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of nullable values. - /// - public static double? Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - long sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - { - checked - { - sum += (long)num; - count++; - } - } - - if (count == 0) - return null; - - return (double?)sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double? Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - public static long? Min( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - public static long? Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - public static long? Max( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || max != null && x.Value < max.Value); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - public static long? Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static float Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - float sum = 0; - foreach (var num in source) - sum = sum + num; - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static float Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of values. - /// - public static float Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - float sum = 0; - long count = 0; - - foreach (var num in source) - { - checked - { - sum += num; - count++; - } - } - - if (count == 0) - throw new InvalidOperationException(); - - return sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static float Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static float? Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - float sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static float? Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of nullable values. - /// - public static float? Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - float sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - { - checked - { - sum += (float)num; - count++; - } - } - - if (count == 0) - return null; - - return (float?)sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static float? Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - public static float? Min( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - public static float? Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - public static float? Max( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || max != null && x.Value < max.Value); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - public static float? Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - - /// - /// Computes the sum of a sequence of values. - /// - public static double Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - double sum = 0; - foreach (var num in source) - sum = sum + num; - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static double Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of values. - /// - public static double Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - double sum = 0; - long count = 0; - - foreach (var num in source) - { - checked - { - sum += num; - count++; - } - } - - if (count == 0) - throw new InvalidOperationException(); - - return sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static double? Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - double sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static double? Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of nullable values. - /// - public static double? Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - double sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - { - checked - { - sum += (double)num; - count++; - } - } - - if (count == 0) - return null; - - return (double?)sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static double? Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - public static double? Min( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - public static double? Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - public static double? Max( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || max != null && x.Value < max.Value); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - public static double? Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - - /// - /// Computes the sum of a sequence of values. - /// - public static decimal Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - decimal sum = 0; - foreach (var num in source) - sum = sum + num; - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static decimal Sum( - this IEnumerable source, - Func selector - ) - { - CheckNotNull(source, "source"); - CheckNotNull(selector, "selector"); - - decimal sum = 0; - foreach (var item in source) sum += selector(item); - - return sum; - } - - /// - /// Computes the average of a sequence of values. - /// - public static decimal Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - decimal sum = 0; - long count = 0; - - foreach (var num in source) - { - checked - { - sum += num; - count++; - } - } - - if (count == 0) - throw new InvalidOperationException(); - - return sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static decimal Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - - /// - /// Computes the sum of a sequence of nullable values. - /// - public static decimal? Sum( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - decimal sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - public static decimal? Sum( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Sum(); - - /// - /// Computes the average of a sequence of nullable values. - /// - public static decimal? Average( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - decimal sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - { - checked - { - sum += (decimal)num; - count++; - } - } - - if (count == 0) - return null; - - return (decimal?)sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - public static decimal? Average( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Average(); - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - public static decimal? Min( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - public static decimal? Min( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Min(); - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - public static decimal? Max( - this IEnumerable source - ) - { - CheckNotNull(source, "source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || max != null && x.Value < max.Value); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - public static decimal? Max( - this IEnumerable source, - Func selector - ) => - source.Select(selector).Max(); - } - - /// - /// Represents a collection of objects that have a common key. - /// - internal interface IGrouping : IEnumerable - { - /// - /// Gets the key of the . - /// - - TKey Key { get; } - } - - /// - /// Defines an indexer, size property, and Boolean search method for - /// data structures that map keys to - /// sequences of values. - /// - internal interface ILookup : IEnumerable> - { - int Count { get; } - IEnumerable this[TKey key] { get; } - - bool Contains(TKey key); - } - - /// - /// Represents a sorted sequence. - /// - internal interface IOrderedEnumerable : IEnumerable - { - /// - /// Performs a subsequent ordering on the elements of an - /// according to a key. - /// - IOrderedEnumerable CreateOrderedEnumerable( - Func keySelector, IComparer comparer, bool descending - ); - } - - /// - /// Represents a collection of keys each mapped to one or more values. - /// - internal sealed class Lookup : ILookup - { - private readonly Dictionary> _map; - - internal Lookup(IEqualityComparer comparer) => _map = new Dictionary>(comparer); - - /// - /// Gets the number of key/value collection pairs in the . - /// - - public int Count => _map.Count; - - /// - /// Gets the collection of values indexed by the specified key. - /// - - public IEnumerable this[TKey key] - { - get - { - IGrouping result; - return _map.TryGetValue(key, out result) ? result : Enumerable.Empty(); - } - } - - internal void Add(IGrouping item) => _map.Add(item.Key, item); - - internal IEnumerable Find(TKey key) - { - IGrouping grouping; - return _map.TryGetValue(key, out grouping) ? grouping : null; - } - - /// - /// Determines whether a specified key is in the . - /// - public bool Contains(TKey key) => _map.ContainsKey(key); - - /// - /// Applies a transform function to each key and its associated - /// values and returns the results. - /// - public IEnumerable ApplyResultSelector( - Func, TResult> resultSelector - ) - { - if (resultSelector == null) - throw new ArgumentNullException("resultSelector"); - - foreach (var pair in _map) - yield return resultSelector(pair.Key, pair.Value); - } - - /// - /// Returns a generic enumerator that iterates through the . - /// - public IEnumerator> GetEnumerator() => _map.Values.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - internal sealed class OrderedEnumerable : IOrderedEnumerable - { - private readonly List> _comparisons; - private readonly IEnumerable _source; - - public OrderedEnumerable(IEnumerable source, - Func keySelector, IComparer comparer, bool descending - ) : - this(source, null, keySelector, comparer, descending) { } - - private OrderedEnumerable(IEnumerable source, List> comparisons, - Func keySelector, IComparer comparer, bool descending - ) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - - _source = source; - - comparer = comparer ?? Comparer.Default; - - if (comparisons == null) - comparisons = new List>( /* capacity */ 4); - - comparisons.Add((x, y) - => (descending ? -1 : 1) * comparer.Compare(keySelector(x), keySelector(y))); - - _comparisons = comparisons; - } - - public IOrderedEnumerable CreateOrderedEnumerable( - Func keySelector, IComparer comparer, bool descending - ) => - new OrderedEnumerable(_source, _comparisons, keySelector, comparer, descending); - - public IEnumerator GetEnumerator() - { - // - // We sort using List.Sort, but docs say that it performs an - // unstable sort. LINQ, on the other hand, says OrderBy performs - // a stable sort. So convert the source sequence into a sequence - // of tuples where the second element tags the position of the - // element from the source sequence (First). The position is - // then used as a tie breaker when all keys compare equal, - // thus making the sort stable. - // - - var list = _source.Select(TagPosition).ToList(); - - list.Sort((x, y) => - { - // - // Compare keys from left to right. - // - - var comparisons = _comparisons; - for (var i = 0; i < comparisons.Count; i++) - { - var result = comparisons[i](x.First, y.First); - if (result != 0) - return result; - } - - // - // All keys compared equal so now break the tie by their - // position in the original sequence, making the sort stable. - // - - return x.Second.CompareTo(y.Second); - }); - - return list.Select(GetFirst).GetEnumerator(); - } - - /// - /// See issue #11 - /// for why this method is needed and cannot be expressed as a - /// lambda at the call site. - /// - private static Tuple TagPosition(T e, int i) => new(e, i); - - /// - /// See issue #11 - /// for why this method is needed and cannot be expressed as a - /// lambda at the call site. - /// - private static T GetFirst(Tuple pv) => pv.First; - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - [Serializable] - internal readonly struct Tuple : IEquatable> - { - public TFirst First { get; } - public TSecond Second { get; } - - public Tuple(TFirst first, TSecond second) - : this() - { - First = first; - Second = second; - } - - public override bool Equals(object obj) => - obj != null - && obj is Tuple - && base.Equals((Tuple)obj); - - public bool Equals(Tuple other) => - EqualityComparer.Default.Equals(other.First, First) - && EqualityComparer.Default.Equals(other.Second, Second); - - public override int GetHashCode() - { - var num = 0x7a2f0b42; - num = -1521134295 * num + EqualityComparer.Default.GetHashCode(First); - return -1521134295 * num + EqualityComparer.Default.GetHashCode(Second); - } - - public override string ToString() => string.Format(CultureInfo.InvariantCulture, @"{{ First = {0}, Second = {1} }}", First, Second); - } -} - -//namespace Elastic.Apm.Libraries.Newtonsoft.Json.Serialization -//{ -//#pragma warning disable 1591 -// internal delegate TResult Func(); - -// internal delegate TResult Func(T a); - -// internal delegate TResult Func(T1 arg1, T2 arg2); - -// internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - -// internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - -// internal delegate void Action(); - -// internal delegate void Action(T1 arg1, T2 arg2); - -// internal delegate void Action(T1 arg1, T2 arg2, T3 arg3); - -// internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -//#pragma warning restore 1591 -//} - -namespace System.Runtime.CompilerServices -{ - /// - /// This attribute allows us to define extension methods without - /// requiring .NET Framework 3.5. For more information, see the section, - /// Extension Methods in .NET Framework 2.0 Apps, - /// of Basic Instincts: Extension Methods - /// column in MSDN Magazine, - /// issue Nov 2007. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] - internal sealed class ExtensionAttribute : Attribute { } -} - -#endif diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MathUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MathUtils.cs deleted file mode 100644 index 928df2e14..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MathUtils.cs +++ /dev/null @@ -1,126 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class MathUtils - { - public static int IntLength(ulong i) - { - if (i < 10000000000) - { - if (i < 10) return 1; - - if (i < 100) return 2; - - if (i < 1000) return 3; - - if (i < 10000) return 4; - - if (i < 100000) return 5; - - if (i < 1000000) return 6; - - if (i < 10000000) return 7; - - if (i < 100000000) return 8; - - if (i < 1000000000) return 9; - - return 10; - } - if (i < 100000000000) return 11; - - if (i < 1000000000000) return 12; - - if (i < 10000000000000) return 13; - - if (i < 100000000000000) return 14; - - if (i < 1000000000000000) return 15; - - if (i < 10000000000000000) return 16; - - if (i < 100000000000000000) return 17; - - if (i < 1000000000000000000) return 18; - - if (i < 10000000000000000000) return 19; - - return 20; - } - - public static char IntToHex(int n) - { - if (n <= 9) return (char)(n + 48); - - return (char)(n - 10 + 97); - } - - public static int? Min(int? val1, int? val2) - { - if (val1 == null) return val2; - - if (val2 == null) return val1; - - return Math.Min(val1.GetValueOrDefault(), val2.GetValueOrDefault()); - } - - public static int? Max(int? val1, int? val2) - { - if (val1 == null) return val2; - - if (val2 == null) return val1; - - return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); - } - - public static double? Max(double? val1, double? val2) - { - if (val1 == null) return val2; - - if (val2 == null) return val1; - - return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); - } - - public static bool ApproxEquals(double d1, double d2) - { - const double epsilon = 2.2204460492503131E-16; - - if (d1 == d2) return true; - - var tolerance = (Math.Abs(d1) + Math.Abs(d2) + 10.0) * epsilon; - var difference = d1 - d2; - - return -tolerance < difference && tolerance > difference; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodBinder.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodBinder.cs deleted file mode 100644 index 466f36c5f..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodBinder.cs +++ /dev/null @@ -1,343 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if !HAVE_LINQ -#else -#endif - -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ -#if PORTABLE - internal static class MethodBinder - { - - /// - /// List of primitive types which can be widened. - /// - private static readonly Type[] PrimitiveTypes = new Type[] - { - typeof(bool), typeof(char), typeof(sbyte), typeof(byte), - typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(float), typeof(double) - }; - - /// - /// Widening masks for primitive types above. - /// Index of the value in this array defines a type we're widening, - /// while the bits in mask define types it can be widened to (including itself). - /// - /// For example, value at index 0 defines a bool type, and it only has bit 0 set, - /// i.e. bool values can be assigned only to bool. - /// - private static readonly int[] WideningMasks = new int[] - { - 0x0001, 0x0FE2, 0x0D54, 0x0FFA, - 0x0D50, 0x0FE2, 0x0D40, 0x0F80, - 0x0D00, 0x0E00, 0x0C00, 0x0800 - }; - - /// - /// Checks if value of primitive type can be - /// assigned to parameter of primitive type . - /// - /// Source primitive type. - /// Target primitive type. - /// true if source type can be widened to target type, false otherwise. - private static bool CanConvertPrimitive(Type from, Type to) - { - if (from == to) - { - // same type - return true; - } - - int fromMask = 0; - int toMask = 0; - - for (int i = 0; i < PrimitiveTypes.Length; i++) - { - if (PrimitiveTypes[i] == from) - { - fromMask = WideningMasks[i]; - } - else if (PrimitiveTypes[i] == to) - { - toMask = 1 << i; - } - - if (fromMask != 0 && toMask != 0) - { - break; - } - } - - return (fromMask & toMask) != 0; - } - - /// - /// Checks if a set of values with given can be used - /// to invoke a method with specified . - /// - /// Method parameters. - /// Argument types. - /// Try to pack extra arguments into the last parameter when it is marked up with . - /// true if method can be called with given arguments, false otherwise. - private static bool FilterParameters(ParameterInfo[] parameters, IList types, bool enableParamArray) - { - ValidationUtils.ArgumentNotNull(parameters, nameof(parameters)); - ValidationUtils.ArgumentNotNull(types, nameof(types)); - - if (parameters.Length == 0) - { - // fast check for parameterless methods - return types.Count == 0; - } - if (parameters.Length > types.Count) - { - // not all declared parameters were specified (optional parameters are not supported) - return false; - } - - // check if the last parameter is ParamArray - Type? paramArrayType = null; - - if (enableParamArray) - { - ParameterInfo lastParam = parameters[parameters.Length - 1]; - if (lastParam.ParameterType.IsArray && lastParam.IsDefined(typeof(ParamArrayAttribute))) - { - paramArrayType = lastParam.ParameterType.GetElementType(); - } - } - - if (paramArrayType == null && parameters.Length != types.Count) - { - // when there's no ParamArray, number of parameters should match - return false; - } - - for (int i = 0; i < types.Count; i++) - { - Type paramType = (paramArrayType != null && i >= parameters.Length - 1) ? paramArrayType : parameters[i].ParameterType; - - if (paramType == types[i]) - { - // exact match with provided type - continue; - } - - if (paramType == typeof(object)) - { - // parameter of type object matches anything - continue; - } - - if (paramType.IsPrimitive()) - { - if (!types[i].IsPrimitive() || !CanConvertPrimitive(types[i], paramType)) - { - // primitive parameter can only be assigned from compatible primitive type - return false; - } - } - else - { - if (!paramType.IsAssignableFrom(types[i])) - { - return false; - } - } - } - - return true; - } - - /// - /// Compares two sets of parameters to determine - /// which one suits better for given argument types. - /// - private class ParametersMatchComparer : IComparer - { - private readonly IList _types; - private readonly bool _enableParamArray; - - public ParametersMatchComparer(IList types, bool enableParamArray) - { - ValidationUtils.ArgumentNotNull(types, nameof(types)); - - _types = types; - _enableParamArray = enableParamArray; - } - - public int Compare(ParameterInfo[] parameters1, ParameterInfo[] parameters2) - { - ValidationUtils.ArgumentNotNull(parameters1, nameof(parameters1)); - ValidationUtils.ArgumentNotNull(parameters2, nameof(parameters2)); - - // parameterless method wins - if (parameters1.Length == 0) - { - return -1; - } - if (parameters2.Length == 0) - { - return 1; - } - - Type? paramArrayType1 = null, paramArrayType2 = null; - - if (_enableParamArray) - { - ParameterInfo lastParam1 = parameters1[parameters1.Length - 1]; - if (lastParam1.ParameterType.IsArray && lastParam1.IsDefined(typeof(ParamArrayAttribute))) - { - paramArrayType1 = lastParam1.ParameterType.GetElementType(); - } - - ParameterInfo lastParam2 = parameters2[parameters2.Length - 1]; - if (lastParam2.ParameterType.IsArray && lastParam2.IsDefined(typeof(ParamArrayAttribute))) - { - paramArrayType2 = lastParam2.ParameterType.GetElementType(); - } - - // A method using params always loses to one not using params - if (paramArrayType1 != null && paramArrayType2 == null) - { - return 1; - } - if (paramArrayType2 != null && paramArrayType1 == null) - { - return -1; - } - } - - for (int i = 0; i < _types.Count; i++) - { - Type type1 = (paramArrayType1 != null && i >= parameters1.Length - 1) ? paramArrayType1 : parameters1[i].ParameterType; - Type type2 = (paramArrayType2 != null && i >= parameters2.Length - 1) ? paramArrayType2 : parameters2[i].ParameterType; - - if (type1 == type2) - { - // exact match between parameter types doesn't change score - continue; - } - - // exact match with source type decides winner immediately - if (type1 == _types[i]) - { - return -1; - } - if (type2 == _types[i]) - { - return 1; - } - - int r = ChooseMorePreciseType(type1, type2); - if (r != 0) - { - // winner decided - return r; - } - } - - return 0; - } - - private static int ChooseMorePreciseType(Type type1, Type type2) - { - if (type1.IsByRef || type2.IsByRef) - { - if (type1.IsByRef && type2.IsByRef) - { - type1 = type1.GetElementType(); - type2 = type2.GetElementType(); - } - else if (type1.IsByRef) - { - type1 = type1.GetElementType(); - if (type1 == type2) - { - return 1; - } - } - else - { - type2 = type2.GetElementType(); - if (type2 == type1) - { - return -1; - } - } - } - - bool c1FromC2, c2FromC1; - - if (type1.IsPrimitive() && type2.IsPrimitive()) - { - c1FromC2 = CanConvertPrimitive(type2, type1); - c2FromC1 = CanConvertPrimitive(type1, type2); - } - else - { - c1FromC2 = type1.IsAssignableFrom(type2); - c2FromC1 = type2.IsAssignableFrom(type1); - } - - if (c1FromC2 == c2FromC1) - { - return 0; - } - - return c1FromC2 ? 1 : -1; - } - - } - - /// - /// Returns a best method overload for given argument . - /// - /// List of method candidates. - /// Argument types. - /// Best method overload, or null if none matched. - public static TMethod SelectMethod(IEnumerable candidates, IList types) where TMethod : MethodBase - { - ValidationUtils.ArgumentNotNull(candidates, nameof(candidates)); - ValidationUtils.ArgumentNotNull(types, nameof(types)); - - // ParamArrays are not supported by ReflectionDelegateFactory - // They will be treated like ordinary array arguments - const bool enableParamArray = false; - - return candidates - .Where(m => FilterParameters(m.GetParameters(), types, enableParamArray)) - .OrderBy(m => m.GetParameters(), new ParametersMatchComparer(types, enableParamArray)) - .FirstOrDefault(); - } - - } -#endif -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodCall.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodCall.cs deleted file mode 100644 index a3da5ddb3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MethodCall.cs +++ /dev/null @@ -1,32 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal delegate TResult MethodCall(T target, params object?[] args); -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs deleted file mode 100644 index 8e1005c2c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs +++ /dev/null @@ -1,153 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Text.RegularExpressions; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal delegate T Creator(); - - internal static class MiscellaneousUtils - { - [Conditional("DEBUG")] - public static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) => Debug.Assert(condition, message); - - public static bool ValueEquals(object? objA, object? objB) - { - if (objA == objB) return true; - - if (objA == null || objB == null) return false; - - // comparing an Int32 and Int64 both of the same value returns false - // make types the same then compare - if (objA.GetType() != objB.GetType()) - { - if (ConvertUtils.IsInteger(objA) && ConvertUtils.IsInteger(objB)) - return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture)); - - if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal)) - { - return MathUtils.ApproxEquals(Convert.ToDouble(objA, CultureInfo.CurrentCulture), - Convert.ToDouble(objB, CultureInfo.CurrentCulture)); - } - - return false; - } - - return objA.Equals(objB); - } - - public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string paramName, object actualValue, string message) - { - var newMessage = message + Environment.NewLine + @"Actual value was {0}.".FormatWith(CultureInfo.InvariantCulture, actualValue); - - return new ArgumentOutOfRangeException(paramName, newMessage); - } - - public static string ToString(object? value) - { - if (value == null) return "{null}"; - - return value is string s ? @"""" + s + @"""" : value!.ToString(); - } - - public static int ByteArrayCompare(byte[] a1, byte[] a2) - { - var lengthCompare = a1.Length.CompareTo(a2.Length); - if (lengthCompare != 0) return lengthCompare; - - for (var i = 0; i < a1.Length; i++) - { - var valueCompare = a1[i].CompareTo(a2[i]); - if (valueCompare != 0) return valueCompare; - } - - return 0; - } - - public static string? GetPrefix(string qualifiedName) - { - GetQualifiedNameParts(qualifiedName, out var prefix, out _); - - return prefix; - } - - public static string GetLocalName(string qualifiedName) - { - GetQualifiedNameParts(qualifiedName, out _, out var localName); - - return localName; - } - - public static void GetQualifiedNameParts(string qualifiedName, out string? prefix, out string localName) - { - var colonPosition = qualifiedName.IndexOf(':'); - - if (colonPosition == -1 || colonPosition == 0 || qualifiedName.Length - 1 == colonPosition) - { - prefix = null; - localName = qualifiedName; - } - else - { - prefix = qualifiedName.Substring(0, colonPosition); - localName = qualifiedName.Substring(colonPosition + 1); - } - } - - internal static RegexOptions GetRegexOptions(string optionsText) - { - var options = RegexOptions.None; - - for (var i = 0; i < optionsText.Length; i++) - { - switch (optionsText[i]) - { - case 'i': - options |= RegexOptions.IgnoreCase; - break; - case 'm': - options |= RegexOptions.Multiline; - break; - case 's': - options |= RegexOptions.Singleline; - break; - case 'x': - options |= RegexOptions.ExplicitCapture; - break; - } - } - - return options; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/NullableAttributes.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/NullableAttributes.cs deleted file mode 100644 index 0816c1e8c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/NullableAttributes.cs +++ /dev/null @@ -1,80 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#nullable enable -namespace System.Diagnostics.CodeAnalysis -{ - /// Specifies that an output will not be null even if the corresponding type allows it. - [AttributeUsage( - AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, - AllowMultiple = true)] - internal sealed class NotNullAttribute : Attribute { } - - /// - /// Specifies that when a method returns , the parameter will not be null even if the - /// corresponding type allows it. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } - - /// Specifies that an output may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)] - internal sealed class MaybeNullAttribute : Attribute { } - - /// Specifies that null is allowed as an input even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property)] - internal sealed class AllowNullAttribute : Attribute { } - - /// - /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal class DoesNotReturnIfAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to - /// the associated parameter matches this value. - /// - public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; - - /// Gets the condition parameter value. - public bool ParameterValue { get; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs deleted file mode 100644 index b68d61d91..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs +++ /dev/null @@ -1,85 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Globalization; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; - -#if !HAVE_LINQ - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal abstract class ReflectionDelegateFactory - { - public abstract Func CreateDefaultConstructor(Type type); - - public abstract Func CreateGet(PropertyInfo propertyInfo); - - public abstract Func CreateGet(FieldInfo fieldInfo); - - public abstract MethodCall CreateMethodCall(MethodBase method); - - public abstract ObjectConstructor CreateParameterizedConstructor(MethodBase method); - - public abstract Action CreateSet(FieldInfo fieldInfo); - - public abstract Action CreateSet(PropertyInfo propertyInfo); - - public Func CreateGet(MemberInfo memberInfo) - { - if (memberInfo is PropertyInfo propertyInfo) - { - // https://github.com/dotnet/corefx/issues/26053 - if (propertyInfo.PropertyType.IsByRef) - { - throw new InvalidOperationException( - "Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, - propertyInfo)); - } - - return CreateGet(propertyInfo); - } - - if (memberInfo is FieldInfo fieldInfo) return CreateGet(fieldInfo); - - throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); - } - - public Action CreateSet(MemberInfo memberInfo) - { - if (memberInfo is PropertyInfo propertyInfo) return CreateSet(propertyInfo); - - if (memberInfo is FieldInfo fieldInfo) return CreateSet(fieldInfo); - - throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionObject.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionObject.cs deleted file mode 100644 index 0a0e72ac3..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionObject.cs +++ /dev/null @@ -1,147 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; - -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class ReflectionMember - { - public Func? Getter { get; set; } - public Type? MemberType { get; set; } - public Action? Setter { get; set; } - } - - internal class ReflectionObject - { - private ReflectionObject(ObjectConstructor? creator) - { - Members = new Dictionary(); - Creator = creator; - } - - public ObjectConstructor? Creator { get; } - public IDictionary Members { get; } - - public object? GetValue(object target, string member) - { - var getter = Members[member].Getter!; - return getter(target); - } - - public void SetValue(object target, string member, object? value) - { - var setter = Members[member].Setter!; - setter(target, value); - } - - public Type GetType(string member) => Members[member].MemberType!; - - public static ReflectionObject Create(Type t, params string[] memberNames) => Create(t, null, memberNames); - - public static ReflectionObject Create(Type t, MethodBase? creator, params string[] memberNames) - { - var delegateFactory = JsonTypeReflector.ReflectionDelegateFactory; - - ObjectConstructor? creatorConstructor = null; - if (creator != null) - creatorConstructor = delegateFactory.CreateParameterizedConstructor(creator); - else - { - if (ReflectionUtils.HasDefaultConstructor(t, false)) - { - var ctor = delegateFactory.CreateDefaultConstructor(t); - - creatorConstructor = args => ctor(); - } - } - - var d = new ReflectionObject(creatorConstructor); - - foreach (var memberName in memberNames) - { - var members = t.GetMember(memberName, BindingFlags.Instance | BindingFlags.Public); - if (members.Length != 1) - throw new ArgumentException("Expected a single member with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, memberName)); - - var member = members.Single(); - - var reflectionMember = new ReflectionMember(); - - switch (member.MemberType()) - { - case MemberTypes.Field: - case MemberTypes.Property: - if (ReflectionUtils.CanReadMemberValue(member, false)) reflectionMember.Getter = delegateFactory.CreateGet(member); - - if (ReflectionUtils.CanSetMemberValue(member, false, false)) - reflectionMember.Setter = delegateFactory.CreateSet(member); - break; - case MemberTypes.Method: - var method = (MethodInfo)member; - if (method.IsPublic) - { - var parameters = method.GetParameters(); - if (parameters.Length == 0 && method.ReturnType != typeof(void)) - { - var call = delegateFactory.CreateMethodCall(method); - reflectionMember.Getter = target => call(target); - } - else if (parameters.Length == 1 && method.ReturnType == typeof(void)) - { - var call = delegateFactory.CreateMethodCall(method); - reflectionMember.Setter = (target, arg) => call(target, arg); - } - } - break; - default: - throw new ArgumentException( - "Unexpected member type '{0}' for member '{1}'.".FormatWith(CultureInfo.InvariantCulture, member.MemberType(), - member.Name)); - } - - reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(member); - - d.Members[memberName] = reflectionMember; - } - - return d; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionUtils.cs deleted file mode 100644 index 5096440d2..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ /dev/null @@ -1,987 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -#if HAVE_BIG_INTEGER -using System.Numerics; -#endif -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Reflection; -using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ -#if (DOTNET || PORTABLE || PORTABLE40) && !NETSTANDARD2_0 - [Flags] - internal enum MemberTypes - { - Event = 2, - Field = 4, - Method = 8, - Property = 16 - } -#endif - -#if PORTABLE && !NETSTANDARD2_0 - [Flags] - internal enum BindingFlags - { - Default = 0, - IgnoreCase = 1, - DeclaredOnly = 2, - Instance = 4, - Static = 8, - Public = 16, - NonPublic = 32, - FlattenHierarchy = 64, - InvokeMethod = 256, - CreateInstance = 512, - GetField = 1024, - SetField = 2048, - GetProperty = 4096, - SetProperty = 8192, - PutDispProperty = 16384, - ExactBinding = 65536, - PutRefDispProperty = 32768, - SuppressChangeType = 131072, - OptionalParamBinding = 262144, - IgnoreReturn = 16777216 - } -#endif - - internal static class ReflectionUtils - { - public static readonly Type[] EmptyTypes; - - static ReflectionUtils() - { -#if HAVE_EMPTY_TYPES - EmptyTypes = Type.EmptyTypes; -#else - EmptyTypes = CollectionUtils.ArrayEmpty(); -#endif - } - - public static bool IsVirtual(this PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - var m = propertyInfo.GetGetMethod(true); - if (m != null && m.IsVirtual) return true; - - m = propertyInfo.GetSetMethod(true); - if (m != null && m.IsVirtual) return true; - - return false; - } - - public static MethodInfo? GetBaseDefinition(this PropertyInfo propertyInfo) - { - ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - - var m = propertyInfo.GetGetMethod(true); - if (m != null) return m.GetBaseDefinition(); - - return propertyInfo.GetSetMethod(true)?.GetBaseDefinition(); - } - - public static bool IsPublic(PropertyInfo property) - { - var getMethod = property.GetGetMethod(); - if (getMethod != null && getMethod.IsPublic) return true; - - var setMethod = property.GetSetMethod(); - if (setMethod != null && setMethod.IsPublic) return true; - - return false; - } - - public static Type? GetObjectType(object? v) => v?.GetType(); - - public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, ISerializationBinder? binder) - { - var fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder); - - switch (assemblyFormat) - { - case TypeNameAssemblyFormatHandling.Simple: - return RemoveAssemblyDetails(fullyQualifiedTypeName); - case TypeNameAssemblyFormatHandling.Full: - return fullyQualifiedTypeName; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder? binder) - { - if (binder != null) - { - binder.BindToName(t, out var assemblyName, out var typeName); -#if (NET20 || NET35) - // for older SerializationBinder implementations that didn't have BindToName - if (assemblyName == null & typeName == null) - { - return t.AssemblyQualifiedName; - } -#endif - return typeName + (assemblyName == null ? "" : ", " + assemblyName); - } - - return t.AssemblyQualifiedName; - } - - private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) - { - var builder = new StringBuilder(); - - // loop through the type name and filter out qualified assembly details from nested type names - var writingAssemblyName = false; - var skippingAssemblyDetails = false; - for (var i = 0; i < fullyQualifiedTypeName.Length; i++) - { - var current = fullyQualifiedTypeName[i]; - switch (current) - { - case '[': - case ']': - writingAssemblyName = false; - skippingAssemblyDetails = false; - builder.Append(current); - break; - case ',': - if (!writingAssemblyName) - { - writingAssemblyName = true; - builder.Append(current); - } - else - skippingAssemblyDetails = true; - break; - default: - if (!skippingAssemblyDetails) builder.Append(current); - break; - } - } - - return builder.ToString(); - } - - public static bool HasDefaultConstructor(Type t, bool nonPublic) - { - ValidationUtils.ArgumentNotNull(t, nameof(t)); - - if (t.IsValueType()) return true; - - return GetDefaultConstructor(t, nonPublic) != null; - } - - public static ConstructorInfo GetDefaultConstructor(Type t) => GetDefaultConstructor(t, false); - - public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic) - { - var bindingFlags = BindingFlags.Instance | BindingFlags.Public; - if (nonPublic) bindingFlags = bindingFlags | BindingFlags.NonPublic; - - return t.GetConstructors(bindingFlags).SingleOrDefault(c => !c.GetParameters().Any()); - } - - public static bool IsNullable(Type t) - { - ValidationUtils.ArgumentNotNull(t, nameof(t)); - - if (t.IsValueType()) return IsNullableType(t); - - return true; - } - - public static bool IsNullableType(Type t) - { - ValidationUtils.ArgumentNotNull(t, nameof(t)); - - return t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(Nullable<>); - } - - public static Type EnsureNotNullableType(Type t) => - IsNullableType(t) - ? Nullable.GetUnderlyingType(t) - : t; - - public static Type EnsureNotByRefType(Type t) => - t.IsByRef && t.HasElementType - ? t.GetElementType() - : t; - - public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition) - { - if (!type.IsGenericType()) return false; - - var t = type.GetGenericTypeDefinition(); - return t == genericInterfaceDefinition; - } - - public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition) => - ImplementsGenericDefinition(type, genericInterfaceDefinition, out _); - - public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, [NotNullWhen(true)] out Type? implementingType) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, nameof(genericInterfaceDefinition)); - - if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition()) - { - throw new ArgumentNullException( - "'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition)); - } - - if (type.IsInterface()) - { - if (type.IsGenericType()) - { - var interfaceDefinition = type.GetGenericTypeDefinition(); - - if (genericInterfaceDefinition == interfaceDefinition) - { - implementingType = type; - return true; - } - } - } - - foreach (var i in type.GetInterfaces()) - { - if (i.IsGenericType()) - { - var interfaceDefinition = i.GetGenericTypeDefinition(); - - if (genericInterfaceDefinition == interfaceDefinition) - { - implementingType = i; - return true; - } - } - } - - implementingType = null; - return false; - } - - public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition) => - InheritsGenericDefinition(type, genericClassDefinition, out _); - - public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type? implementingType) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - ValidationUtils.ArgumentNotNull(genericClassDefinition, nameof(genericClassDefinition)); - - if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition()) - { - throw new ArgumentNullException( - "'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition)); - } - - return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType); - } - - private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type? implementingType) - { - do - { - if (currentType.IsGenericType() && genericClassDefinition == currentType.GetGenericTypeDefinition()) - { - implementingType = currentType; - return true; - } - - currentType = currentType.BaseType(); - } while (currentType != null); - - implementingType = null; - return false; - } - - /// - /// Gets the type of the typed collection's items. - /// - /// The type. - /// The type of the typed collection's items. - public static Type? GetCollectionItemType(Type type) - { - ValidationUtils.ArgumentNotNull(type, nameof(type)); - - if (type.IsArray) return type.GetElementType(); - - if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out var genericListType)) - { - if (genericListType!.IsGenericTypeDefinition()) - throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); - - return genericListType!.GetGenericArguments()[0]; - } - if (typeof(IEnumerable).IsAssignableFrom(type)) return null; - - throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); - } - - public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type? keyType, out Type? valueType) - { - ValidationUtils.ArgumentNotNull(dictionaryType, nameof(dictionaryType)); - - if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out var genericDictionaryType)) - { - if (genericDictionaryType!.IsGenericTypeDefinition()) - throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); - - var dictionaryGenericArguments = genericDictionaryType!.GetGenericArguments(); - - keyType = dictionaryGenericArguments[0]; - valueType = dictionaryGenericArguments[1]; - return; - } - if (typeof(IDictionary).IsAssignableFrom(dictionaryType)) - { - keyType = null; - valueType = null; - return; - } - - throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); - } - - /// - /// Gets the member's underlying type. - /// - /// The member. - /// The underlying type of the member. - public static Type GetMemberUnderlyingType(MemberInfo member) - { - ValidationUtils.ArgumentNotNull(member, nameof(member)); - - switch (member.MemberType()) - { - case MemberTypes.Field: - return ((FieldInfo)member).FieldType; - case MemberTypes.Property: - return ((PropertyInfo)member).PropertyType; - case MemberTypes.Event: - return ((EventInfo)member).EventHandlerType; - case MemberTypes.Method: - return ((MethodInfo)member).ReturnType; - default: - throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo, EventInfo or MethodInfo", nameof(member)); - } - } - - public static bool IsByRefLikeType(Type type) - { - if (!type.IsValueType()) return false; - - // IsByRefLike flag on type is not available in netstandard2.0 - var attributes = GetAttributes(type, null, false); - for (var i = 0; i < attributes.Length; i++) - { - if (string.Equals(attributes[i].GetType().FullName, "System.Runtime.CompilerServices.IsByRefLikeAttribute", StringComparison.Ordinal)) - return true; - } - - return false; - } - - /// - /// Determines whether the property is an indexed property. - /// - /// The property. - /// - /// true if the property is an indexed property; otherwise, false. - /// - public static bool IsIndexedProperty(PropertyInfo property) - { - ValidationUtils.ArgumentNotNull(property, nameof(property)); - - return property.GetIndexParameters().Length > 0; - } - - /// - /// Gets the member's value on the object. - /// - /// The member. - /// The target object. - /// The member's value on the object. - public static object GetMemberValue(MemberInfo member, object target) - { - ValidationUtils.ArgumentNotNull(member, nameof(member)); - ValidationUtils.ArgumentNotNull(target, nameof(target)); - - switch (member.MemberType()) - { - case MemberTypes.Field: - return ((FieldInfo)member).GetValue(target); - case MemberTypes.Property: - try - { - return ((PropertyInfo)member).GetValue(target, null); - } - catch (TargetParameterCountException e) - { - throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), e); - } - default: - throw new ArgumentException( - "MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), - nameof(member)); - } - } - - /// - /// Sets the member's value on the target object. - /// - /// The member. - /// The target. - /// The value. - public static void SetMemberValue(MemberInfo member, object target, object? value) - { - ValidationUtils.ArgumentNotNull(member, nameof(member)); - ValidationUtils.ArgumentNotNull(target, nameof(target)); - - switch (member.MemberType()) - { - case MemberTypes.Field: - ((FieldInfo)member).SetValue(target, value); - break; - case MemberTypes.Property: - ((PropertyInfo)member).SetValue(target, value, null); - break; - default: - throw new ArgumentException( - "MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), - nameof(member)); - } - } - - /// - /// Determines whether the specified MemberInfo can be read. - /// - /// The MemberInfo to determine whether can be read. - /// /// - /// if set to true then allow the member to be gotten non-publicly. - /// - /// true if the specified MemberInfo can be read; otherwise, false. - /// - public static bool CanReadMemberValue(MemberInfo member, bool nonPublic) - { - switch (member.MemberType()) - { - case MemberTypes.Field: - var fieldInfo = (FieldInfo)member; - - if (nonPublic) - return true; - else if (fieldInfo.IsPublic) return true; - - return false; - case MemberTypes.Property: - var propertyInfo = (PropertyInfo)member; - - if (!propertyInfo.CanRead) return false; - - if (nonPublic) return true; - - return propertyInfo.GetGetMethod(nonPublic) != null; - default: - return false; - } - } - - /// - /// Determines whether the specified MemberInfo can be set. - /// - /// The MemberInfo to determine whether can be set. - /// if set to true then allow the member to be set non-publicly. - /// if set to true then allow the member to be set if read-only. - /// - /// true if the specified MemberInfo can be set; otherwise, false. - /// - public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly) - { - switch (member.MemberType()) - { - case MemberTypes.Field: - var fieldInfo = (FieldInfo)member; - - if (fieldInfo.IsLiteral) return false; - - if (fieldInfo.IsInitOnly && !canSetReadOnly) return false; - - if (nonPublic) return true; - - if (fieldInfo.IsPublic) return true; - - return false; - case MemberTypes.Property: - var propertyInfo = (PropertyInfo)member; - - if (!propertyInfo.CanWrite) return false; - - if (nonPublic) return true; - - return propertyInfo.GetSetMethod(nonPublic) != null; - default: - return false; - } - } - - public static List GetFieldsAndProperties(Type type, BindingFlags bindingAttr) - { - var targetMembers = new List(); - - targetMembers.AddRange(GetFields(type, bindingAttr)); - targetMembers.AddRange(GetProperties(type, bindingAttr)); - - // for some reason .NET returns multiple members when overriding a generic member on a base class - // http://social.msdn.microsoft.com/Forums/en-US/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/reflection-overriden-abstract-generic-properties?forum=netfxbcl - // filter members to only return the override on the topmost class - // update: I think this is fixed in .NET 3.5 SP1 - leave this in for now... - var distinctMembers = new List(targetMembers.Count); - - foreach (var groupedMember in targetMembers.GroupBy(m => m.Name)) - { - var count = groupedMember.Count(); - - if (count == 1) - distinctMembers.Add(groupedMember.First()); - else - { - var resolvedMembers = new List(); - foreach (var memberInfo in groupedMember) - { - // this is a bit hacky - // if the hiding property is hiding a base property and it is virtual - // then this ensures the derived property gets used - if (resolvedMembers.Count == 0) - resolvedMembers.Add(memberInfo); - else if (!IsOverridenGenericMember(memberInfo, bindingAttr) || memberInfo.Name == "Item") - { - // two members with the same name were declared on a type - // this can be done via IL emit, e.g. Moq - if (resolvedMembers.Any(m => m.DeclaringType == memberInfo.DeclaringType)) continue; - - resolvedMembers.Add(memberInfo); - } - } - - distinctMembers.AddRange(resolvedMembers); - } - } - - return distinctMembers; - } - - private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr) - { - if (memberInfo.MemberType() != MemberTypes.Property) return false; - - var propertyInfo = (PropertyInfo)memberInfo; - if (!IsVirtual(propertyInfo)) return false; - - var declaringType = propertyInfo.DeclaringType; - if (!declaringType.IsGenericType()) return false; - - var genericTypeDefinition = declaringType.GetGenericTypeDefinition(); - if (genericTypeDefinition == null) return false; - - var members = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr); - if (members.Length == 0) return false; - - var memberUnderlyingType = GetMemberUnderlyingType(members[0]); - if (!memberUnderlyingType.IsGenericParameter) return false; - - return true; - } - - public static T? GetAttribute(object attributeProvider) where T : Attribute => GetAttribute(attributeProvider, true); - - public static T? GetAttribute(object attributeProvider, bool inherit) where T : Attribute - { - var attributes = GetAttributes(attributeProvider, inherit); - - return attributes?.FirstOrDefault(); - } - -#if !(DOTNET || PORTABLE) || NETSTANDARD2_0 - public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute - { - var a = GetAttributes(attributeProvider, typeof(T), inherit); - - if (a is T[] attributes) return attributes; - - return a.Cast().ToArray(); - } - - public static Attribute[] GetAttributes(object attributeProvider, Type? attributeType, bool inherit) - { - ValidationUtils.ArgumentNotNull(attributeProvider, nameof(attributeProvider)); - - var provider = attributeProvider; - - // http://hyperthink.net/blog/getcustomattributes-gotcha/ - // ICustomAttributeProvider doesn't do inheritance - - switch (provider) - { - case Type t: - var array = attributeType != null ? t.GetCustomAttributes(attributeType, inherit) : t.GetCustomAttributes(inherit); - var attributes = array.Cast().ToArray(); - -#if (NET20 || NET35) - // ye olde .NET GetCustomAttributes doesn't respect the inherit argument - if (inherit && t.BaseType != null) - { - attributes = attributes.Union(GetAttributes(t.BaseType, attributeType, inherit)).ToArray(); - } -#endif - - return attributes; - case Assembly a: - return attributeType != null ? Attribute.GetCustomAttributes(a, attributeType) : Attribute.GetCustomAttributes(a); - case MemberInfo mi: - return attributeType != null - ? Attribute.GetCustomAttributes(mi, attributeType, inherit) - : Attribute.GetCustomAttributes(mi, inherit); -#if !PORTABLE40 - case Module m: - return attributeType != null - ? Attribute.GetCustomAttributes(m, attributeType, inherit) - : Attribute.GetCustomAttributes(m, inherit); -#endif - case ParameterInfo p: - return attributeType != null - ? Attribute.GetCustomAttributes(p, attributeType, inherit) - : Attribute.GetCustomAttributes(p, inherit); - default: -#if !PORTABLE40 - var customAttributeProvider = (ICustomAttributeProvider)attributeProvider; - var result = attributeType != null - ? customAttributeProvider.GetCustomAttributes(attributeType, inherit) - : customAttributeProvider.GetCustomAttributes(inherit); - - return (Attribute[])result; -#else - throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider)); -#endif - } - } -#else - public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute - { - return GetAttributes(attributeProvider, typeof(T), inherit).Cast().ToArray(); - } - - public static Attribute[] GetAttributes(object provider, Type? attributeType, bool inherit) - { - switch (provider) - { - case Type t: - return (attributeType != null) - ? t.GetTypeInfo().GetCustomAttributes(attributeType, inherit).ToArray() - : t.GetTypeInfo().GetCustomAttributes(inherit).ToArray(); - case Assembly a: - return (attributeType != null) ? a.GetCustomAttributes(attributeType).ToArray() : a.GetCustomAttributes().ToArray(); - case MemberInfo memberInfo: - return (attributeType != null) ? memberInfo.GetCustomAttributes(attributeType, inherit).ToArray() : memberInfo.GetCustomAttributes(inherit).ToArray(); - case Module module: - return (attributeType != null) ? module.GetCustomAttributes(attributeType).ToArray() : module.GetCustomAttributes().ToArray(); - case ParameterInfo parameterInfo: - return (attributeType != null) ? parameterInfo.GetCustomAttributes(attributeType, inherit).ToArray() : parameterInfo.GetCustomAttributes(inherit).ToArray(); - } - - throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider)); - } -#endif - - public static StructMultiKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName) - { - var assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName); - - string typeName; - string? assemblyName; - - if (assemblyDelimiterIndex != null) - { - typeName = fullyQualifiedTypeName.Trim(0, assemblyDelimiterIndex.GetValueOrDefault()); - assemblyName = fullyQualifiedTypeName.Trim(assemblyDelimiterIndex.GetValueOrDefault() + 1, - fullyQualifiedTypeName.Length - assemblyDelimiterIndex.GetValueOrDefault() - 1); - } - else - { - typeName = fullyQualifiedTypeName; - assemblyName = null; - } - - return new StructMultiKey(assemblyName, typeName); - } - - private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName) - { - // we need to get the first comma following all surrounded in brackets because of generic types - // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - var scope = 0; - for (var i = 0; i < fullyQualifiedTypeName.Length; i++) - { - var current = fullyQualifiedTypeName[i]; - switch (current) - { - case '[': - scope++; - break; - case ']': - scope--; - break; - case ',': - if (scope == 0) return i; - - break; - } - } - - return null; - } - - public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo) - { - const BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; - - switch (memberInfo.MemberType()) - { - case MemberTypes.Property: - var propertyInfo = (PropertyInfo)memberInfo; - - var types = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray(); - - return targetType.GetProperty(propertyInfo.Name, bindingAttr, null, propertyInfo.PropertyType, types, null); - default: - return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), bindingAttr).SingleOrDefault(); - } - } - - public static IEnumerable GetFields(Type targetType, BindingFlags bindingAttr) - { - ValidationUtils.ArgumentNotNull(targetType, nameof(targetType)); - - var fieldInfos = new List(targetType.GetFields(bindingAttr)); -#if !PORTABLE - // Type.GetFields doesn't return inherited private fields - // manually find private fields from base class - GetChildPrivateFields(fieldInfos, targetType, bindingAttr); -#endif - - return fieldInfos.Cast(); - } - -#if !PORTABLE - private static void GetChildPrivateFields(IList initialFields, Type targetType, BindingFlags bindingAttr) - { - // fix weirdness with private FieldInfos only being returned for the current Type - // find base type fields and add them to result - if ((bindingAttr & BindingFlags.NonPublic) != 0) - { - // modify flags to not search for public fields - var nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public); - - while ((targetType = targetType.BaseType()) != null) - { - // filter out protected fields - var childPrivateFields = - targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate); - - initialFields.AddRange(childPrivateFields); - } - } - } -#endif - - public static IEnumerable GetProperties(Type targetType, BindingFlags bindingAttr) - { - ValidationUtils.ArgumentNotNull(targetType, nameof(targetType)); - - var propertyInfos = new List(targetType.GetProperties(bindingAttr)); - - // GetProperties on an interface doesn't return properties from its interfaces - if (targetType.IsInterface()) - { - foreach (var i in targetType.GetInterfaces()) - propertyInfos.AddRange(i.GetProperties(bindingAttr)); - } - - GetChildPrivateProperties(propertyInfos, targetType, bindingAttr); - - // a base class private getter/setter will be inaccessible unless the property was gotten from the base class - for (var i = 0; i < propertyInfos.Count; i++) - { - var member = propertyInfos[i]; - if (member.DeclaringType != targetType) - { - var declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType, member); - propertyInfos[i] = declaredMember; - } - } - - return propertyInfos; - } - - public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag) => - (bindingAttr & flag) == flag - ? bindingAttr ^ flag - : bindingAttr; - - private static void GetChildPrivateProperties(IList initialProperties, Type targetType, BindingFlags bindingAttr) - { - // fix weirdness with private PropertyInfos only being returned for the current Type - // find base type properties and add them to result - - // also find base properties that have been hidden by subtype properties with the same name - - while ((targetType = targetType.BaseType()) != null) - { - foreach (var propertyInfo in targetType.GetProperties(bindingAttr)) - { - var subTypeProperty = propertyInfo; - - if (!subTypeProperty.IsVirtual()) - { - if (!IsPublic(subTypeProperty)) - { - // have to test on name rather than reference because instances are different - // depending on the type that GetProperties was called on - var index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name); - if (index == -1) - initialProperties.Add(subTypeProperty); - else - { - var childProperty = initialProperties[index]; - // don't replace public child with private base - if (!IsPublic(childProperty)) - { - // replace nonpublic properties for a child, but gotten from - // the parent with the one from the child - // the property gotten from the child will have access to private getter/setter - initialProperties[index] = subTypeProperty; - } - } - } - else - { - var index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name - && p.DeclaringType == subTypeProperty.DeclaringType); - - if (index == -1) initialProperties.Add(subTypeProperty); - } - } - else - { - var subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType; - - var index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name - && p.IsVirtual() - && (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType).IsAssignableFrom(subTypePropertyDeclaringType)); - - // don't add a virtual property that has an override - if (index == -1) initialProperties.Add(subTypeProperty); - } - } - } - } - - public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method) - { - var isMethodOverriden = currentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .Any(info => - info.Name == method && - // check that the method overrides the original on DynamicObjectProxy - info.DeclaringType != methodDeclaringType - && info.GetBaseDefinition().DeclaringType == methodDeclaringType - ); - - return isMethodOverriden; - } - - public static object? GetDefaultValue(Type type) - { - if (!type.IsValueType()) return null; - - switch (ConvertUtils.GetTypeCode(type)) - { - case PrimitiveTypeCode.Boolean: - return false; - case PrimitiveTypeCode.Char: - case PrimitiveTypeCode.SByte: - case PrimitiveTypeCode.Byte: - case PrimitiveTypeCode.Int16: - case PrimitiveTypeCode.UInt16: - case PrimitiveTypeCode.Int32: - case PrimitiveTypeCode.UInt32: - return 0; - case PrimitiveTypeCode.Int64: - case PrimitiveTypeCode.UInt64: - return 0L; - case PrimitiveTypeCode.Single: - return 0f; - case PrimitiveTypeCode.Double: - return 0.0; - case PrimitiveTypeCode.Decimal: - return 0m; - case PrimitiveTypeCode.DateTime: - return new DateTime(); -#if HAVE_BIG_INTEGER - case PrimitiveTypeCode.BigInteger: - return new BigInteger(); -#endif - case PrimitiveTypeCode.Guid: - return new Guid(); -#if HAVE_DATE_TIME_OFFSET - case PrimitiveTypeCode.DateTimeOffset: - return new DateTimeOffset(); -#endif - } - - if (IsNullable(type)) return null; - - // possibly use IL initobj for perf here? - return Activator.CreateInstance(type); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringBuffer.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringBuffer.cs deleted file mode 100644 index 9c9439756..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringBuffer.cs +++ /dev/null @@ -1,99 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - /// - /// Builds a string. Unlike this class lets you reuse its internal buffer. - /// - internal struct StringBuffer - { - public int Position { get; set; } - - public bool IsEmpty => InternalBuffer == null; - - public StringBuffer(IArrayPool? bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize)) { } - - private StringBuffer(char[] buffer) - { - InternalBuffer = buffer; - Position = 0; - } - - public void Append(IArrayPool? bufferPool, char value) - { - // test if the buffer array is large enough to take the value - if (Position == InternalBuffer!.Length) EnsureSize(bufferPool, 1); - - // set value and increment poisition - InternalBuffer![Position++] = value; - } - - public void Append(IArrayPool? bufferPool, char[] buffer, int startIndex, int count) - { - if (Position + count >= InternalBuffer!.Length) EnsureSize(bufferPool, count); - - Array.Copy(buffer, startIndex, InternalBuffer, Position, count); - - Position += count; - } - - public void Clear(IArrayPool? bufferPool) - { - if (InternalBuffer != null) - { - BufferUtils.ReturnBuffer(bufferPool, InternalBuffer); - InternalBuffer = null; - } - Position = 0; - } - - private void EnsureSize(IArrayPool? bufferPool, int appendLength) - { - var newBuffer = BufferUtils.RentBuffer(bufferPool, (Position + appendLength) * 2); - - if (InternalBuffer != null) - { - Array.Copy(InternalBuffer, newBuffer, Position); - BufferUtils.ReturnBuffer(bufferPool, InternalBuffer); - } - - InternalBuffer = newBuffer; - } - - public override string ToString() => ToString(0, Position); - - public string ToString(int start, int length) => - // TODO: validation - new(InternalBuffer, start, length); - - public char[]? InternalBuffer { get; private set; } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringReference.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringReference.cs deleted file mode 100644 index 7a7b8806c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringReference.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal readonly struct StringReference - { - public char this[int i] => Chars[i]; - - public char[] Chars { get; } - - public int StartIndex { get; } - - public int Length { get; } - - public StringReference(char[] chars, int startIndex, int length) - { - Chars = chars; - StartIndex = startIndex; - Length = length; - } - - public override string ToString() => new(Chars, StartIndex, Length); - } - - internal static class StringReferenceExtensions - { - public static int IndexOf(this StringReference s, char c, int startIndex, int length) - { - var index = Array.IndexOf(s.Chars, c, s.StartIndex + startIndex, length); - if (index == -1) return -1; - - return index - s.StartIndex; - } - - public static bool StartsWith(this StringReference s, string text) - { - if (text.Length > s.Length) return false; - - var chars = s.Chars; - - for (var i = 0; i < text.Length; i++) - if (text[i] != chars[i + s.StartIndex]) - return false; - - return true; - } - - public static bool EndsWith(this StringReference s, string text) - { - if (text.Length > s.Length) return false; - - var chars = s.Chars; - - var start = s.StartIndex + s.Length - text.Length; - for (var i = 0; i < text.Length; i++) - if (text[i] != chars[i + start]) - return false; - - return true; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringUtils.cs deleted file mode 100644 index 9861b6125..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StringUtils.cs +++ /dev/null @@ -1,293 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Text; -#if !HAVE_LINQ -using Elastic.Apm.Libraries.Newtonsoft.Json.Utilities.LinqBridge; - -#else -using System.Linq; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class StringUtils - { - public const char CarriageReturn = '\r'; - public const string CarriageReturnLineFeed = "\r\n"; - public const string Empty = ""; - public const char LineFeed = '\n'; - public const char Tab = '\t'; - - public static bool IsNullOrEmpty([NotNullWhen(false)] string? value) => string.IsNullOrEmpty(value); - - public static string FormatWith(this string format, IFormatProvider provider, object? arg0) => format.FormatWith(provider, new[] { arg0 }); - - public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1) => - format.FormatWith(provider, new[] { arg0, arg1 }); - - public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2) => - format.FormatWith(provider, new[] { arg0, arg1, arg2 }); - - public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2, object? arg3) => - format.FormatWith(provider, new[] { arg0, arg1, arg2, arg3 }); - - private static string FormatWith(this string format, IFormatProvider provider, params object?[] args) - { - // leave this a private to force code to use an explicit overload - // avoids stack memory being reserved for the object array - ValidationUtils.ArgumentNotNull(format, nameof(format)); - - return string.Format(provider, format, args); - } - - /// - /// Determines whether the string is all white space. Empty string will return false. - /// - /// The string to test whether it is all white space. - /// - /// true if the string is all white space; otherwise, false. - /// - public static bool IsWhiteSpace(string s) - { - if (s == null) throw new ArgumentNullException(nameof(s)); - - if (s.Length == 0) return false; - - for (var i = 0; i < s.Length; i++) - { - if (!char.IsWhiteSpace(s[i])) - return false; - } - - return true; - } - - public static StringWriter CreateStringWriter(int capacity) - { - var sb = new StringBuilder(capacity); - var sw = new StringWriter(sb, CultureInfo.InvariantCulture); - - return sw; - } - - public static void ToCharAsUnicode(char c, char[] buffer) - { - buffer[0] = '\\'; - buffer[1] = 'u'; - buffer[2] = MathUtils.IntToHex((c >> 12) & '\x000f'); - buffer[3] = MathUtils.IntToHex((c >> 8) & '\x000f'); - buffer[4] = MathUtils.IntToHex((c >> 4) & '\x000f'); - buffer[5] = MathUtils.IntToHex(c & '\x000f'); - } - - public static TSource ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, - string testValue - ) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - - if (valueSelector == null) throw new ArgumentNullException(nameof(valueSelector)); - - var caseInsensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.OrdinalIgnoreCase)); - if (caseInsensitiveResults.Count() <= 1) - return caseInsensitiveResults.SingleOrDefault(); - - // multiple results returned. now filter using case sensitivity - var caseSensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.Ordinal)); - return caseSensitiveResults.SingleOrDefault(); - } - - public static string ToCamelCase(string s) - { - if (IsNullOrEmpty(s) || !char.IsUpper(s[0])) return s; - - var chars = s.ToCharArray(); - - for (var i = 0; i < chars.Length; i++) - { - if (i == 1 && !char.IsUpper(chars[i])) break; - - var hasNext = i + 1 < chars.Length; - if (i > 0 && hasNext && !char.IsUpper(chars[i + 1])) - { - // if the next character is a space, which is not considered uppercase - // (otherwise we wouldn't be here...) - // we want to ensure that the following: - // 'FOO bar' is rewritten as 'foo bar', and not as 'foO bar' - // The code was written in such a way that the first word in uppercase - // ends when if finds an uppercase letter followed by a lowercase letter. - // now a ' ' (space, (char)32) is considered not upper - // but in that case we still want our current character to become lowercase - if (char.IsSeparator(chars[i + 1])) chars[i] = ToLower(chars[i]); - - break; - } - - chars[i] = ToLower(chars[i]); - } - - return new string(chars); - } - - private static char ToLower(char c) - { -#if HAVE_CHAR_TO_LOWER_WITH_CULTURE - c = char.ToLower(c, CultureInfo.InvariantCulture); -#else - c = char.ToLowerInvariant(c); -#endif - return c; - } - - public static string ToSnakeCase(string s) => ToSeparatedCase(s, '_'); - - public static string ToKebabCase(string s) => ToSeparatedCase(s, '-'); - - private static string ToSeparatedCase(string s, char separator) - { - if (IsNullOrEmpty(s)) return s; - - var sb = new StringBuilder(); - var state = SeparatedCaseState.Start; - - for (var i = 0; i < s.Length; i++) - { - if (s[i] == ' ') - { - if (state != SeparatedCaseState.Start) state = SeparatedCaseState.NewWord; - } - else if (char.IsUpper(s[i])) - { - switch (state) - { - case SeparatedCaseState.Upper: - var hasNext = i + 1 < s.Length; - if (i > 0 && hasNext) - { - var nextChar = s[i + 1]; - if (!char.IsUpper(nextChar) && nextChar != separator) sb.Append(separator); - } - break; - case SeparatedCaseState.Lower: - case SeparatedCaseState.NewWord: - sb.Append(separator); - break; - } - - char c; -#if HAVE_CHAR_TO_LOWER_WITH_CULTURE - c = char.ToLower(s[i], CultureInfo.InvariantCulture); -#else - c = char.ToLowerInvariant(s[i]); -#endif - sb.Append(c); - - state = SeparatedCaseState.Upper; - } - else if (s[i] == separator) - { - sb.Append(separator); - state = SeparatedCaseState.Start; - } - else - { - if (state == SeparatedCaseState.NewWord) sb.Append(separator); - - sb.Append(s[i]); - state = SeparatedCaseState.Lower; - } - } - - return sb.ToString(); - } - - public static bool IsHighSurrogate(char c) - { -#if HAVE_UNICODE_SURROGATE_DETECTION - return char.IsHighSurrogate(c); -#else - return c >= 55296 && c <= 56319; -#endif - } - - public static bool IsLowSurrogate(char c) - { -#if HAVE_UNICODE_SURROGATE_DETECTION - return char.IsLowSurrogate(c); -#else - return c >= 56320 && c <= 57343; -#endif - } - - public static bool StartsWith(this string source, char value) => source.Length > 0 && source[0] == value; - - public static bool EndsWith(this string source, char value) => source.Length > 0 && source[source.Length - 1] == value; - - public static string Trim(this string s, int start, int length) - { - // References: https://referencesource.microsoft.com/#mscorlib/system/string.cs,2691 - // https://referencesource.microsoft.com/#mscorlib/system/string.cs,1226 - if (s == null) throw new ArgumentNullException(); - - if (start < 0) throw new ArgumentOutOfRangeException(nameof(start)); - - if (length < 0) throw new ArgumentOutOfRangeException(nameof(length)); - - var end = start + length - 1; - if (end >= s.Length) throw new ArgumentOutOfRangeException(nameof(length)); - - for (; start < end; start++) - { - if (!char.IsWhiteSpace(s[start])) - break; - } - - for (; end >= start; end--) - { - if (!char.IsWhiteSpace(s[end])) - break; - } - - return s.Substring(start, end - start + 1); - } - - private enum SeparatedCaseState - { - Start, - Lower, - Upper, - NewWord - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StructMultiKey.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StructMultiKey.cs deleted file mode 100644 index 7e8a69da8..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/StructMultiKey.cs +++ /dev/null @@ -1,55 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal readonly struct StructMultiKey : IEquatable> - { - public readonly T1 Value1; - public readonly T2 Value2; - - public StructMultiKey(T1 v1, T2 v2) - { - Value1 = v1; - Value2 = v2; - } - - public override int GetHashCode() => (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0); - - public override bool Equals(object obj) - { - if (!(obj is StructMultiKey key)) return false; - - return Equals(key); - } - - public bool Equals(StructMultiKey other) => Equals(Value1, other.Value1) && Equals(Value2, other.Value2); - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ThreadSafeStore.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ThreadSafeStore.cs deleted file mode 100644 index 508fd9c50..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ThreadSafeStore.cs +++ /dev/null @@ -1,103 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#if !HAVE_LINQ -#endif -#if HAVE_CONCURRENT_DICTIONARY -using System.Collections.Concurrent; -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal class ThreadSafeStore - { -#if HAVE_CONCURRENT_DICTIONARY - private readonly ConcurrentDictionary _concurrentStore; -#else - private readonly object _lock = new(); - private Dictionary _store; -#endif - private readonly Func _creator; - - public ThreadSafeStore(Func creator) - { - ValidationUtils.ArgumentNotNull(creator, nameof(creator)); - - _creator = creator; -#if HAVE_CONCURRENT_DICTIONARY - _concurrentStore = new ConcurrentDictionary(); -#else - _store = new Dictionary(); -#endif - } - - public TValue Get(TKey key) - { -#if HAVE_CONCURRENT_DICTIONARY - return _concurrentStore.GetOrAdd(key, _creator); -#else - if (!_store.TryGetValue(key, out var value)) return AddValue(key); - - return value; -#endif - } - -#if !HAVE_CONCURRENT_DICTIONARY - private TValue AddValue(TKey key) - { - var value = _creator(key); - - lock (_lock) - { - if (_store == null) - { - _store = new Dictionary(); - _store[key] = value; - } - else - { - // double check locking - if (_store.TryGetValue(key, out var checkValue)) return checkValue; - - var newStore = new Dictionary(_store); - newStore[key] = value; - -#if HAVE_MEMORY_BARRIER - Thread.MemoryBarrier(); -#endif - _store = newStore; - } - - return value; - } - } -#endif - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/TypeExtensions.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/TypeExtensions.cs deleted file mode 100644 index a627fe83c..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/TypeExtensions.cs +++ /dev/null @@ -1,630 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; - -#if !HAVE_LINQ - -#else -#endif - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class TypeExtensions - { -#if DOTNET || PORTABLE -#if !DOTNET - private static readonly BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; - - public static MethodInfo? GetGetMethod(this PropertyInfo propertyInfo) - { - return propertyInfo.GetGetMethod(false); - } - - public static MethodInfo? GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic) - { - MethodInfo getMethod = propertyInfo.GetMethod; - if (getMethod != null && (getMethod.IsPublic || nonPublic)) - { - return getMethod; - } - - return null; - } - - public static MethodInfo? GetSetMethod(this PropertyInfo propertyInfo) - { - return propertyInfo.GetSetMethod(false); - } - - public static MethodInfo? GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic) - { - MethodInfo setMethod = propertyInfo.SetMethod; - if (setMethod != null && (setMethod.IsPublic || nonPublic)) - { - return setMethod; - } - - return null; - } -#endif - - public static bool IsSubclassOf(this Type type, Type c) - { - return type.GetTypeInfo().IsSubclassOf(c); - } - -#if !DOTNET - public static bool IsAssignableFrom(this Type type, Type c) - { - return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo()); - } -#endif - - public static bool IsInstanceOfType(this Type type, object? o) - { - if (o == null) - { - return false; - } - - return type.IsAssignableFrom(o.GetType()); - } -#endif - - public static MethodInfo Method(this Delegate d) - { -#if HAVE_FULL_REFLECTION - return d.Method; -#else - return d.GetMethodInfo(); -#endif - } - - public static MemberTypes MemberType(this MemberInfo memberInfo) - { -#if !(DOTNET || PORTABLE || PORTABLE40) - return memberInfo.MemberType; -#else - if (memberInfo is PropertyInfo) - { - return MemberTypes.Property; - } - else if (memberInfo is FieldInfo) - { - return MemberTypes.Field; - } - else if (memberInfo is EventInfo) - { - return MemberTypes.Event; - } - else if (memberInfo is MethodInfo) - { - return MemberTypes.Method; - } - else - { - return default; - } -#endif - } - - public static bool ContainsGenericParameters(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.ContainsGenericParameters; -#else - return type.GetTypeInfo().ContainsGenericParameters; -#endif - } - - public static bool IsInterface(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsInterface; -#else - return type.GetTypeInfo().IsInterface; -#endif - } - - public static bool IsGenericType(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsGenericType; -#else - return type.GetTypeInfo().IsGenericType; -#endif - } - - public static bool IsGenericTypeDefinition(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsGenericTypeDefinition; -#else - return type.GetTypeInfo().IsGenericTypeDefinition; -#endif - } - - public static Type BaseType(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.BaseType; -#else - return type.GetTypeInfo().BaseType; -#endif - } - - public static Assembly Assembly(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.Assembly; -#else - return type.GetTypeInfo().Assembly; -#endif - } - - public static bool IsEnum(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsEnum; -#else - return type.GetTypeInfo().IsEnum; -#endif - } - - public static bool IsClass(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsClass; -#else - return type.GetTypeInfo().IsClass; -#endif - } - - public static bool IsSealed(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsSealed; -#else - return type.GetTypeInfo().IsSealed; -#endif - } - -#if (PORTABLE40 || DOTNET || PORTABLE) - public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object? placeholder1, Type propertyType, IList indexParameters, object? placeholder2) - { - IEnumerable propertyInfos = type.GetProperties(bindingFlags); - - return propertyInfos.Where(p => - { - if (name != null && name != p.Name) - { - return false; - } - if (propertyType != null && propertyType != p.PropertyType) - { - return false; - } - if (indexParameters != null) - { - if (!p.GetIndexParameters().Select(ip => ip.ParameterType).SequenceEqual(indexParameters)) - { - return false; - } - } - - return true; - }).SingleOrDefault(); - } - - public static IEnumerable GetMember(this Type type, string name, MemberTypes memberType, BindingFlags bindingFlags) - { -#if PORTABLE - return type.GetMemberInternal(name, memberType, bindingFlags); -#else - return type.GetMember(name, bindingFlags).Where(m => - { - if ((m.MemberType() | memberType) != memberType) - { - return false; - } - - return true; - }); -#endif - } -#endif - -#if (DOTNET || PORTABLE) - public static MethodInfo GetBaseDefinition(this MethodInfo method) - { - return method.GetRuntimeBaseDefinition(); - } -#endif - -#if (DOTNET || PORTABLE) - public static bool IsDefined(this Type type, Type attributeType, bool inherit) - { - return type.GetTypeInfo().CustomAttributes.Any(a => a.AttributeType == attributeType); - } - -#if !DOTNET - - public static MethodInfo GetMethod(this Type type, string name) - { - return type.GetMethod(name, DefaultFlags); - } - - public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags) - { - return type.GetTypeInfo().GetDeclaredMethod(name); - } - - public static MethodInfo GetMethod(this Type type, IList parameterTypes) - { - return type.GetMethod(null, parameterTypes); - } - - public static MethodInfo GetMethod(this Type type, string? name, IList parameterTypes) - { - return type.GetMethod(name, DefaultFlags, null, parameterTypes, null); - } - - public static MethodInfo GetMethod(this Type type, string? name, BindingFlags bindingFlags, object? placeHolder1, IList parameterTypes, object? placeHolder2) - { - return MethodBinder.SelectMethod(type.GetTypeInfo().DeclaredMethods.Where(m => (name == null || m.Name == name) && TestAccessibility(m, bindingFlags)), parameterTypes); - } - - public static IEnumerable GetConstructors(this Type type) - { - return type.GetConstructors(DefaultFlags); - } - - public static IEnumerable GetConstructors(this Type type, BindingFlags bindingFlags) - { - return type.GetTypeInfo().DeclaredConstructors.Where(c => TestAccessibility(c, bindingFlags)); - } - - public static ConstructorInfo GetConstructor(this Type type, IList parameterTypes) - { - return type.GetConstructor(DefaultFlags, null, parameterTypes, null); - } - - public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object? placeholder1, IList parameterTypes, object? placeholder2) - { - return MethodBinder.SelectMethod(type.GetConstructors(bindingFlags), parameterTypes); - } - - public static MemberInfo[] GetMember(this Type type, string member) - { - return type.GetMemberInternal(member, null, DefaultFlags); - } - - public static MemberInfo[] GetMember(this Type type, string member, BindingFlags bindingFlags) - { - return type.GetMemberInternal(member, null, bindingFlags); - } - - public static MemberInfo[] GetMemberInternal(this Type type, string member, MemberTypes? memberType, BindingFlags bindingFlags) - { - return type.GetTypeInfo().GetMembersRecursive().Where(m => - m.Name == member && - // test type before accessibility - accessibility doesn't support some types - (memberType == null || (m.MemberType() | memberType) == memberType) && - TestAccessibility(m, bindingFlags)).ToArray(); - } - - public static FieldInfo? GetField(this Type type, string member) - { - return type.GetField(member, DefaultFlags); - } - - public static FieldInfo? GetField(this Type type, string member, BindingFlags bindingFlags) - { - FieldInfo field = type.GetTypeInfo().GetDeclaredField(member); - if (field == null || !TestAccessibility(field, bindingFlags)) - { - return null; - } - - return field; - } - - public static IEnumerable GetProperties(this Type type, BindingFlags bindingFlags) - { - IList properties = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly)) - ? type.GetTypeInfo().DeclaredProperties.ToList() - : type.GetTypeInfo().GetPropertiesRecursive(); - - return properties.Where(p => TestAccessibility(p, bindingFlags)); - } - - private static bool ContainsMemberName(IEnumerable members, string name) - { - foreach (MemberInfo memberInfo in members) - { - if (memberInfo.Name == name) - { - return true; - } - } - - return false; - } - - private static IList GetMembersRecursive(this TypeInfo type) - { - TypeInfo? t = type; - List members = new List(); - while (t != null) - { - foreach (MemberInfo member in t.DeclaredMembers) - { - if (!ContainsMemberName(members, member.Name)) - { - members.Add(member); - } - } - t = t.BaseType?.GetTypeInfo(); - } - - return members; - } - - private static IList GetPropertiesRecursive(this TypeInfo type) - { - TypeInfo? t = type; - List properties = new List(); - while (t != null) - { - foreach (PropertyInfo member in t.DeclaredProperties) - { - if (!ContainsMemberName(properties, member.Name)) - { - properties.Add(member); - } - } - t = t.BaseType?.GetTypeInfo(); - } - - return properties; - } - - private static IList GetFieldsRecursive(this TypeInfo type) - { - TypeInfo? t = type; - List fields = new List(); - while (t != null) - { - foreach (FieldInfo member in t.DeclaredFields) - { - if (!ContainsMemberName(fields, member.Name)) - { - fields.Add(member); - } - } - t = t.BaseType?.GetTypeInfo(); - } - - return fields; - } - - public static IEnumerable GetMethods(this Type type, BindingFlags bindingFlags) - { - return type.GetTypeInfo().DeclaredMethods; - } - - public static PropertyInfo? GetProperty(this Type type, string name) - { - return type.GetProperty(name, DefaultFlags); - } - - public static PropertyInfo? GetProperty(this Type type, string name, BindingFlags bindingFlags) - { - PropertyInfo property = type.GetTypeInfo().GetDeclaredProperty(name); - if (property == null || !TestAccessibility(property, bindingFlags)) - { - return null; - } - - return property; - } - - public static IEnumerable GetFields(this Type type) - { - return type.GetFields(DefaultFlags); - } - - public static IEnumerable GetFields(this Type type, BindingFlags bindingFlags) - { - IList fields = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly)) - ? type.GetTypeInfo().DeclaredFields.ToList() - : type.GetTypeInfo().GetFieldsRecursive(); - - return fields.Where(f => TestAccessibility(f, bindingFlags)).ToList(); - } - - private static bool TestAccessibility(PropertyInfo member, BindingFlags bindingFlags) - { - if (member.GetMethod != null && TestAccessibility(member.GetMethod, bindingFlags)) - { - return true; - } - - if (member.SetMethod != null && TestAccessibility(member.SetMethod, bindingFlags)) - { - return true; - } - - return false; - } - - private static bool TestAccessibility(MemberInfo member, BindingFlags bindingFlags) - { - if (member is FieldInfo f) - { - return TestAccessibility(f, bindingFlags); - } - else if (member is MethodBase m) - { - return TestAccessibility(m, bindingFlags); - } - else if (member is PropertyInfo p) - { - return TestAccessibility(p, bindingFlags); - } - - throw new ArgumentOutOfRangeException("Unexpected member type."); - } - - private static bool TestAccessibility(FieldInfo member, BindingFlags bindingFlags) - { - bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) || - (!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic)); - - bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) || - (!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance)); - - return visibility && instance; - } - - private static bool TestAccessibility(MethodBase member, BindingFlags bindingFlags) - { - bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) || - (!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic)); - - bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) || - (!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance)); - - return visibility && instance; - } - - public static Type[] GetGenericArguments(this Type type) - { - return type.GetTypeInfo().GenericTypeArguments; - } - - public static IEnumerable GetInterfaces(this Type type) - { - return type.GetTypeInfo().ImplementedInterfaces; - } - - public static IEnumerable GetMethods(this Type type) - { - return type.GetTypeInfo().DeclaredMethods; - } -#endif -#endif - - public static bool IsAbstract(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsAbstract; -#else - return type.GetTypeInfo().IsAbstract; -#endif - } - - public static bool IsVisible(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsVisible; -#else - return type.GetTypeInfo().IsVisible; -#endif - } - - public static bool IsValueType(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsValueType; -#else - return type.GetTypeInfo().IsValueType; -#endif - } - - public static bool IsPrimitive(this Type type) - { -#if HAVE_FULL_REFLECTION - return type.IsPrimitive; -#else - return type.GetTypeInfo().IsPrimitive; -#endif - } - - public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, [NotNullWhen(true)] out Type? match) - { - var current = type; - - while (current != null) - { - if (string.Equals(current.FullName, fullTypeName, StringComparison.Ordinal)) - { - match = current; - return true; - } - - current = current.BaseType(); - } - - if (searchInterfaces) - { - foreach (var i in type.GetInterfaces()) - { - if (string.Equals(i.Name, fullTypeName, StringComparison.Ordinal)) - { - match = type; - return true; - } - } - } - - match = null; - return false; - } - - public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces) => - type.AssignableToTypeName(fullTypeName, searchInterfaces, out _); - - public static bool ImplementInterface(this Type type, Type interfaceType) - { - for (var currentType = type; currentType != null; currentType = currentType.BaseType()) - { - IEnumerable interfaces = currentType.GetInterfaces(); - foreach (var i in interfaces) - if (i == interfaceType || i != null && i.ImplementInterface(interfaceType)) - return true; - } - - return false; - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ValidationUtils.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ValidationUtils.cs deleted file mode 100644 index ac7223d4b..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ValidationUtils.cs +++ /dev/null @@ -1,41 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; -using System.Diagnostics.CodeAnalysis; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json.Utilities -{ - internal static class ValidationUtils - { - public static void ArgumentNotNull([NotNull] object? value, string parameterName) - { - if (value == null) throw new ArgumentNullException(parameterName); - } - } -} diff --git a/src/Elastic.Apm/Libraries/Newtonsoft.Json/WriteState.cs b/src/Elastic.Apm/Libraries/Newtonsoft.Json/WriteState.cs deleted file mode 100644 index 54fd76051..000000000 --- a/src/Elastic.Apm/Libraries/Newtonsoft.Json/WriteState.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region License - -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using System; - -#nullable enable -namespace Elastic.Apm.Libraries.Newtonsoft.Json -{ - /// - /// Specifies the state of the . - /// - internal enum WriteState - { - /// - /// An exception has been thrown, which has left the in an invalid state. - /// You may call the method to put the in the Closed - /// state. - /// Any other method calls result in an being thrown. - /// - Error = 0, - - /// - /// The method has been called. - /// - Closed = 1, - - /// - /// An object is being written. - /// - Object = 2, - - /// - /// An array is being written. - /// - Array = 3, - - /// - /// A constructor is being written. - /// - Constructor = 4, - - /// - /// A property is being written. - /// - Property = 5, - - /// - /// A write method has not been called. - /// - Start = 6 - } -} diff --git a/src/Elastic.Apm/Metrics/MetricSet.cs b/src/Elastic.Apm/Metrics/MetricSet.cs index b1e33d66d..b6a568077 100644 --- a/src/Elastic.Apm/Metrics/MetricSet.cs +++ b/src/Elastic.Apm/Metrics/MetricSet.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Metrics diff --git a/src/Elastic.Apm/Model/DroppedSpanStats.cs b/src/Elastic.Apm/Model/DroppedSpanStats.cs index 63121a0be..91ad137da 100644 --- a/src/Elastic.Apm/Model/DroppedSpanStats.cs +++ b/src/Elastic.Apm/Model/DroppedSpanStats.cs @@ -4,8 +4,8 @@ // See the LICENSE file in the project root for more information using System; +using System.Text.Json.Serialization; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Model { @@ -30,19 +30,19 @@ double durationSumUs /// DestinationServiceResource identifies the destination service resource being operated on. e.g. 'http://elastic.co:80', /// 'elasticsearch', 'rabbitmq/queue_name'. /// - [JsonProperty("destination_service_resource")] + [JsonPropertyName("destination_service_resource")] public string DestinationServiceResource { get; } /// /// ServiceTargetType identifies the type of the target service being operated on e.g. 'oracle', 'rabbitmq' /// - [JsonProperty("service_target_type")] + [JsonPropertyName("service_target_type")] public string ServiceTargetType { get; } /// /// ServiceTargetName identifies the instance name of the target service being operated on /// - [JsonProperty("service_target_name")] + [JsonPropertyName("service_target_name")] public string ServiceTargetName { get; } /// diff --git a/src/Elastic.Apm/Model/Error.cs b/src/Elastic.Apm/Model/Error.cs index 6aa8fe7ae..2c5fec360 100644 --- a/src/Elastic.Apm/Model/Error.cs +++ b/src/Elastic.Apm/Model/Error.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Config; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Logging; namespace Elastic.Apm.Model @@ -49,7 +49,7 @@ private Error(Transaction transaction, string parentId, IApmLogger logger, Dicti if (labels != null) { foreach (var item in labels) - Context.InternalLabels.Value.InnerDictionary[item.Key] = item.Value; + Context.InternalLabels.InnerDictionary[item.Key] = item.Value; } } @@ -74,7 +74,7 @@ private void CheckAndCaptureBaggage(Transaction transaction) continue; var newKey = $"baggage.{baggage.Key}"; - var labels = Context.InternalLabels.Value; + var labels = Context.InternalLabels; labels[newKey] = baggage.Value; } } @@ -111,7 +111,7 @@ private Error(string culprit, CapturedException capturedException, string id, st public ErrorLog Log { get; set; } [MaxLength] - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } /// @@ -120,13 +120,13 @@ private Error(string culprit, CapturedException capturedException, string id, st public long Timestamp { get; } [MaxLength] - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } public TransactionData Transaction { get; } [MaxLength] - [JsonProperty("transaction_id")] + [JsonPropertyName("transaction_id")] public string TransactionId { get; set; } /// @@ -135,7 +135,7 @@ private Error(string culprit, CapturedException capturedException, string id, st /// See /// the relevant Json.NET Documentation /// - public bool ShouldSerializeContext() => Transaction != null && Transaction.IsSampled; + public bool ShouldSerializeContext() => Transaction is { IsSampled: true }; public override string ToString() => new ToStringBuilder(nameof(Error)) { @@ -155,7 +155,7 @@ internal TransactionData(string name, bool isSampled, string type) /// /// IsSampled indicates whether or not the full information for a transaction is captured. If a transaction is unsampled no spans and less context information will be reported. /// - [JsonProperty("sampled")] + [JsonPropertyName("sampled")] public bool IsSampled { get; } /// diff --git a/src/Elastic.Apm/Model/Faas.cs b/src/Elastic.Apm/Model/Faas.cs index afbf22b94..2ad49720e 100644 --- a/src/Elastic.Apm/Model/Faas.cs +++ b/src/Elastic.Apm/Model/Faas.cs @@ -3,7 +3,8 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Apm.Libraries.Newtonsoft.Json; + +using System.Text.Json.Serialization; namespace Elastic.Apm.Model { @@ -56,7 +57,7 @@ public struct Trigger /// /// The id of the origin trigger request. /// - [JsonProperty("request_id")] + [JsonPropertyName("request_id")] public string RequestId { get; set; } /// diff --git a/src/Elastic.Apm/Model/LabelsDictionary.cs b/src/Elastic.Apm/Model/LabelsDictionary.cs index a42f8b37b..b8306f9b3 100644 --- a/src/Elastic.Apm/Model/LabelsDictionary.cs +++ b/src/Elastic.Apm/Model/LabelsDictionary.cs @@ -4,8 +4,10 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using Elastic.Apm.Helpers; using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.Model @@ -17,10 +19,9 @@ namespace Elastic.Apm.Model /// The reason for this is backwards compatibility - this type makes sure that we don't break user that rely on the old /// interface. /// - [JsonConverter(typeof(LabelsJsonConverter))] - internal class LabelsDictionary : Dictionary + public class LabelsDictionary : Dictionary { - internal Dictionary InnerDictionary { get; } = new Dictionary(); + internal Dictionary InnerDictionary { get; } = new(); /// /// Merges the string dictionary with the InnerDictionary @@ -35,5 +36,15 @@ internal Dictionary MergedDictionary return InnerDictionary; } } + + internal Dictionary ExposeDictionary() => + MergedDictionary.ToDictionary( + k => k.Key + .Truncate() + .Replace('.', '_') + .Replace('*', '_') + .Replace('"', '_'), + v=>v.Value.ToString() + ); } } diff --git a/src/Elastic.Apm/Model/NoopSpan.cs b/src/Elastic.Apm/Model/NoopSpan.cs index 394524a24..651b500d3 100644 --- a/src/Elastic.Apm/Model/NoopSpan.cs +++ b/src/Elastic.Apm/Model/NoopSpan.cs @@ -6,10 +6,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Model { @@ -66,7 +66,7 @@ internal NoopSpan(string name, string type, string subtype, string action, public Outcome Outcome { get; set; } public DistributedTracingData OutgoingDistributedTracingData => null; - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] [MaxLength] public string ParentId { get; } @@ -77,10 +77,11 @@ internal NoopSpan(string name, string type, string subtype, string action, public long Timestamp { get; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] [MaxLength] public string TraceId { get; } + [MaxLength] public string TransactionId { get; } [MaxLength] diff --git a/src/Elastic.Apm/Model/NoopTransaction.cs b/src/Elastic.Apm/Model/NoopTransaction.cs index f7c17eb47..1e1eb5aa8 100644 --- a/src/Elastic.Apm/Model/NoopTransaction.cs +++ b/src/Elastic.Apm/Model/NoopTransaction.cs @@ -6,11 +6,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Config; -using Elastic.Apm.Libraries.Newtonsoft.Json; namespace Elastic.Apm.Model { @@ -65,17 +65,17 @@ IConfiguration configuration public Outcome Outcome { get; set; } public DistributedTracingData OutgoingDistributedTracingData { get; } - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] [MaxLength] public string ParentId { get; } [MaxLength] public string Result { get; set; } - [JsonProperty("span_count")] + [JsonPropertyName("span_count")] public SpanCount SpanCount { get; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] [MaxLength] public string TraceId { get; } diff --git a/src/Elastic.Apm/Model/Span.cs b/src/Elastic.Apm/Model/Span.cs index 707c9f45d..f75e12370 100644 --- a/src/Elastic.Apm/Model/Span.cs +++ b/src/Elastic.Apm/Model/Span.cs @@ -7,12 +7,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Config; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Logging; using Elastic.Apm.Report; using Elastic.Apm.ServerInfo; @@ -291,7 +291,7 @@ public DistributedTracingData OutgoingDistributedTracingData } [MaxLength] - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } /// @@ -311,7 +311,7 @@ public DistributedTracingData OutgoingDistributedTracingData /// /// Captures the sample rate of the agent when this span was created. /// - [JsonProperty("sample_rate")] + [JsonPropertyName("sample_rate")] internal double? SampleRate { get; } private double SelfDuration => Duration.HasValue ? Duration.Value - _childDurationTimer.Duration : 0; @@ -319,7 +319,7 @@ public DistributedTracingData OutgoingDistributedTracingData [JsonIgnore] internal bool ShouldBeSentToApmServer => IsSampled && !_isDropped; - [JsonProperty("stacktrace")] + [JsonPropertyName("stacktrace")] public List StackTrace { get; set; } [MaxLength] @@ -331,11 +331,11 @@ public DistributedTracingData OutgoingDistributedTracingData public long Timestamp { get; internal set; } [MaxLength] - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } [MaxLength] - [JsonProperty("transaction_id")] + [JsonPropertyName("transaction_id")] public string TransactionId => _enclosingTransaction.Id; [MaxLength] @@ -363,7 +363,7 @@ public DistributedTracingData OutgoingDistributedTracingData public bool TryGetLabel(string key, out T value) { - if (Context.InternalLabels.Value.InnerDictionary.TryGetValue(key, out var label)) + if (Context.InternalLabels.InnerDictionary.TryGetValue(key, out var label)) { if (label?.Value is T t) { @@ -879,22 +879,22 @@ private Destination DeduceHttpDestination() } public void SetLabel(string key, string value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, bool value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, double value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, int value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, long value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, decimal value) - => Context.InternalLabels.Value.InnerDictionary[key] = value; + => Context.InternalLabels.InnerDictionary[key] = value; public void CaptureErrorLog(ErrorLog errorLog, string parentId = null, Exception exception = null, Dictionary labels = null) => ExecutionSegmentCommon.CaptureErrorLog( @@ -947,7 +947,7 @@ internal class Composite /// /// A string value indicating which compression strategy was used. The valid values are `exact_match` and `same_kind` /// - [JsonProperty("compression_strategy")] + [JsonPropertyName("compression_strategy")] public string CompressionStrategy { get; set; } /// diff --git a/src/Elastic.Apm/Model/Transaction.cs b/src/Elastic.Apm/Model/Transaction.cs index 3558d7a56..2163a9ad9 100644 --- a/src/Elastic.Apm/Model/Transaction.cs +++ b/src/Elastic.Apm/Model/Transaction.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; @@ -14,7 +15,6 @@ using Elastic.Apm.DiagnosticListeners; using Elastic.Apm.DistributedTracing; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; using Elastic.Apm.Logging; using Elastic.Apm.Metrics.MetricsProvider; using Elastic.Apm.Report; @@ -406,7 +406,7 @@ private void CheckAndCaptureBaggage() [JsonIgnore] public Dictionary Custom => Context.Custom; - [JsonProperty("dropped_spans_stats")] + [JsonPropertyName("dropped_spans_stats")] public IEnumerable DroppedSpanStats => _droppedSpanStatsMap?.Values.ToList(); /// @@ -431,7 +431,7 @@ private void CheckAndCaptureBaggage() [JsonIgnore] internal bool IsContextCreated => _context.IsValueCreated; - [JsonProperty("sampled")] + [JsonPropertyName("sampled")] public bool IsSampled { get; } [JsonIgnore] @@ -495,7 +495,7 @@ public Outcome Outcome public DistributedTracingData OutgoingDistributedTracingData => new(TraceId, Id, IsSampled, _traceState); [MaxLength] - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } /// @@ -510,15 +510,12 @@ public Outcome Outcome /// /// Captures the sample rate of the agent when this transaction was created. /// - [JsonProperty("sample_rate")] + [JsonPropertyName("sample_rate")] internal double? SampleRate { get; } internal double SelfDuration => Duration.HasValue ? Duration.Value - ChildDurationTimer.Duration : 0; - internal Service Service; - - - [JsonProperty("span_count")] + [JsonPropertyName("span_count")] public SpanCount SpanCount { get; set; } /// @@ -527,7 +524,7 @@ public Outcome Outcome public long Timestamp { get; } [MaxLength] - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; } [MaxLength] @@ -745,7 +742,7 @@ public void End() public bool TryGetLabel(string key, out T value) { - if (Context.InternalLabels.Value.InnerDictionary.TryGetValue(key, out var label)) + if (Context.InternalLabels.InnerDictionary.TryGetValue(key, out var label)) { if (label?.Value is T t) { @@ -945,22 +942,22 @@ public void CaptureErrorLog(ErrorLog errorLog, string parentId = null, Exception ); public void SetLabel(string key, string value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, bool value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, double value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, int value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, long value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; public void SetLabel(string key, decimal value) - => _context.Value.InternalLabels.Value.InnerDictionary[key] = value; + => _context.Value.InternalLabels.InnerDictionary[key] = value; private readonly struct DroppedSpanStatsKey : IEquatable { diff --git a/src/Elastic.Apm/Report/IntakeResponse.cs b/src/Elastic.Apm/Report/IntakeResponse.cs index 32389b91a..25d910c1e 100644 --- a/src/Elastic.Apm/Report/IntakeResponse.cs +++ b/src/Elastic.Apm/Report/IntakeResponse.cs @@ -4,22 +4,22 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Elastic.Apm.Report; internal class IntakeResponse { - [JsonProperty("accepted")] + [JsonPropertyName("accepted")] public int Accepted { get; set; } - [JsonProperty("errors")] + [JsonPropertyName("errors")] public IReadOnlyCollection Errors { get; set; } } internal class IntakeError { - [JsonProperty("message")] + [JsonPropertyName("message")] public string Message { get; set; } } diff --git a/src/Elastic.Apm/Report/PayloadSenderV2.cs b/src/Elastic.Apm/Report/PayloadSenderV2.cs index 2e85fa893..cfca94e9e 100644 --- a/src/Elastic.Apm/Report/PayloadSenderV2.cs +++ b/src/Elastic.Apm/Report/PayloadSenderV2.cs @@ -478,7 +478,7 @@ private void ProcessQueueItems(object[] queueItems) } } - private void Serialize(object item, string eventType, TextWriter writer) + private void Serialize(object item, string eventType, StreamWriter writer) { writer.Write("{\""); writer.Write(eventType); diff --git a/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs b/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs index c623a123b..793210ec6 100644 --- a/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs @@ -4,32 +4,80 @@ using System; using System.Collections.Generic; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; -namespace Elastic.Apm.Report.Serialization + +namespace Elastic.Apm.Report.Serialization; + +internal class CustomJsonConverter : JsonConverter> { - internal class CustomJsonConverter : JsonConverter> + public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + JsonSerializer.Deserialize>(ref reader, options); + + public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) { - public override void WriteJson(JsonWriter writer, Dictionary custom, JsonSerializer serializer) + writer.WriteStartObject(); + foreach (var keyValue in value) { - writer.WriteStartObject(); - foreach (var keyValue in custom) - { - writer.WritePropertyName(keyValue.Key.Replace('.', '_') - .Replace('*', '_') - .Replace('"', '_')); - - if (keyValue.Value != null) - writer.WriteValue(keyValue.Value); - else - writer.WriteNull(); - } - writer.WriteEndObject(); + var key = keyValue.Key + .Replace('.', '_') + .Replace('*', '_') + .Replace('"', '_'); + + if (keyValue.Value != null) + writer.WriteString(key, keyValue.Value); + else + writer.WriteNull(key); } + writer.WriteEndObject(); + } +} - public override Dictionary ReadJson(JsonReader reader, Type objectType, Dictionary existingValue, - bool hasExistingValue, JsonSerializer serializer - ) - => serializer.Deserialize>(reader); +public class BooleanConverter : JsonConverter +{ + public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + switch (reader.TokenType) + { + case JsonTokenType.True: + return true; + case JsonTokenType.False: + return false; + case JsonTokenType.String: + return reader.GetString() switch + { + "true" => true, + "false" => false, + _ => throw new JsonException() + }; + default: + throw new JsonException(); + } } + + public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) => + writer.WriteBooleanValue(value); +} + +public class JsonConverterDouble : JsonConverter +{ + public override double Read(ref Utf8JsonReader reader, + Type typeToConvert, JsonSerializerOptions options) => + reader.GetDouble(); + + public override void Write(Utf8JsonWriter writer, double value, + JsonSerializerOptions options) => + writer.WriteRawValue(value.ToString("N1", CultureInfo.InvariantCulture)); +} +public class JsonConverterDecimal : JsonConverter +{ + public override decimal Read(ref Utf8JsonReader reader, + Type typeToConvert, JsonSerializerOptions options) => + reader.GetDecimal(); + + public override void Write(Utf8JsonWriter writer, decimal value, + JsonSerializerOptions options) => + writer.WriteRawValue(value.ToString("N1", CultureInfo.InvariantCulture)); } diff --git a/src/Elastic.Apm/Report/Serialization/ElasticApmContractResolver.cs b/src/Elastic.Apm/Report/Serialization/ElasticApmContractResolver.cs index ef7f0383a..626360050 100644 --- a/src/Elastic.Apm/Report/Serialization/ElasticApmContractResolver.cs +++ b/src/Elastic.Apm/Report/Serialization/ElasticApmContractResolver.cs @@ -5,35 +5,22 @@ using System.Reflection; using Elastic.Apm.Api.Constraints; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Serialization; namespace Elastic.Apm.Report.Serialization { - internal class ElasticApmContractResolver : DefaultContractResolver + internal class ElasticApmContractResolver { - private readonly TruncateJsonConverter _defaultTruncateJsonConverter = - new TruncateJsonConverter(Consts.PropertyMaxLength); + private readonly TruncateJsonConverter _defaultTruncateJsonConverter = new TruncateJsonConverter(Consts.PropertyMaxLength); - public ElasticApmContractResolver() => - NamingStrategy = new CamelCaseNamingStrategy { OverrideSpecifiedNames = true }; - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + protected void CreateProperty(MemberInfo member) { - var property = base.CreateProperty(member, memberSerialization); - - if (property.PropertyType == typeof(string)) + var maxLengthAttribute = member.GetCustomAttribute(); + if (maxLengthAttribute != null) { - var maxLengthAttribute = member.GetCustomAttribute(); - if (maxLengthAttribute != null) - { - property.Converter = maxLengthAttribute.Length == Consts.PropertyMaxLength - ? _defaultTruncateJsonConverter - : new TruncateJsonConverter(maxLengthAttribute.Length); - } + var c = maxLengthAttribute.Length == Consts.PropertyMaxLength + ? _defaultTruncateJsonConverter + : new TruncateJsonConverter(maxLengthAttribute.Length); } - - return property; } } } diff --git a/src/Elastic.Apm/Report/Serialization/LabelsJsonConverter.cs b/src/Elastic.Apm/Report/Serialization/LabelsJsonConverter.cs index 7ad7e93ba..99bfe6947 100644 --- a/src/Elastic.Apm/Report/Serialization/LabelsJsonConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/LabelsJsonConverter.cs @@ -3,85 +3,124 @@ // See the LICENSE file in the project root for more information using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; +using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Model; namespace Elastic.Apm.Report.Serialization { internal class LabelsJsonConverter : JsonConverter { - public override void WriteJson(JsonWriter writer, LabelsDictionary labels, JsonSerializer serializer) + public override void Write(Utf8JsonWriter writer, LabelsDictionary labels, JsonSerializerOptions options) { + if (labels is null or { MergedDictionary.Count: 0 }) + return; + writer.WriteStartObject(); foreach (var keyValue in labels.MergedDictionary) { // Labels are trimmed and also de dotted in order to satisfy the Intake API - writer.WritePropertyName(keyValue.Key.Truncate() + var key = keyValue.Key + .Truncate() .Replace('.', '_') .Replace('*', '_') - .Replace('"', '_')); + .Replace('"', '_'); + + writer.WritePropertyName(key); - if (keyValue.Value != null) + SerializeLabelsDictionaryValues(writer, keyValue); + } + writer.WriteEndObject(); + } + + private static void SerializeLabelsDictionaryValues(Utf8JsonWriter writer, KeyValuePair keyValue) + { + if (keyValue.Value != null) + { + switch (keyValue.Value.Value) { - switch (keyValue.Value.Value) - { - case string strValue: - writer.WriteValue(strValue.Truncate()); - break; - default: - writer.WriteValue(keyValue.Value.Value); - break; - } + case string strValue: + writer.WriteStringValue(strValue.Truncate()); + break; + case bool b: + writer.WriteBooleanValue(b); + break; + case decimal b: + writer.WriteRawValue(b.ToString("N1", CultureInfo.InvariantCulture)); + break; + case double b: + writer.WriteRawValue(b.ToString("N1", CultureInfo.InvariantCulture)); + break; + case int b: + writer.WriteNumberValue(b); + break; + case uint b: + writer.WriteNumberValue(b); + break; + case ulong b: + writer.WriteNumberValue(b); + break; + case long b: + writer.WriteNumberValue(b); + break; + default: + writer.WriteNullValue(); + break; } - else - writer.WriteNull(); } - writer.WriteEndObject(); + else + writer.WriteNullValue(); } - public override LabelsDictionary ReadJson(JsonReader reader, Type objectType, LabelsDictionary existingValue, - bool hasExistingValue, JsonSerializer serializer - ) + public override LabelsDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonToken.Null) + if (reader.TokenType == JsonTokenType.Null) return null; - if (reader.TokenType != JsonToken.StartObject) - throw new JsonException($"expected {JsonToken.StartObject} but received {reader.TokenType}"); + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException($"expected {JsonTokenType.StartObject} but received {reader.TokenType}"); var labels = new LabelsDictionary(); while (reader.Read()) { - if (reader.TokenType == JsonToken.EndObject) + if (reader.TokenType == JsonTokenType.EndObject) break; - var property = (string)reader.Value; + var property = reader.GetString()!; reader.Read(); switch (reader.TokenType) { - case JsonToken.Integer: - labels.InnerDictionary.Add(property, (long)reader.Value); + case JsonTokenType.Number: + if (reader.TryGetInt64(out var longValue)) + labels.InnerDictionary.Add(property, longValue); + else if (reader.TryGetDouble(out var doubleValue)) + labels.InnerDictionary.Add(property, doubleValue); break; - case JsonToken.Float: - labels.InnerDictionary.Add(property, (double)reader.Value); + case JsonTokenType.String: + labels.Add(property, reader.GetString()); break; - case JsonToken.String: - labels.Add(property, (string)reader.Value); + case JsonTokenType.True: + labels.InnerDictionary.Add(property, true); break; - case JsonToken.Boolean: - labels.InnerDictionary.Add(property, (bool)reader.Value); + case JsonTokenType.False: + labels.InnerDictionary.Add(property, false); break; default: throw new JsonException( - $"Expected {JsonToken.Integer}, {JsonToken.Float}, {JsonToken.String} or {JsonToken.Boolean} " + $"Expected {JsonTokenType.Number}, {JsonTokenType.String}, {JsonTokenType.True} or {JsonTokenType.False} " + $"but received {reader.TokenType}"); } } return labels; } + } } diff --git a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs index 6c22599ef..b04fa87b5 100644 --- a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs @@ -4,15 +4,17 @@ using System; using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Metrics; namespace Elastic.Apm.Report.Serialization { internal class MetricSetConverter : JsonConverter { - public override void WriteJson(JsonWriter writer, MetricSet value, JsonSerializer serializer) + public override void Write(Utf8JsonWriter writer, MetricSet value, JsonSerializerOptions options) { writer.WriteStartObject(); if (value.Transaction != null) @@ -23,10 +25,10 @@ public override void WriteJson(JsonWriter writer, MetricSet value, JsonSerialize writer.WriteStartObject(); writer.WritePropertyName("name"); - writer.WriteValue(value.Transaction.Name); + writer.WriteStringValue(value.Transaction.Name); writer.WritePropertyName("type"); - writer.WriteValue(value.Transaction.Type); + writer.WriteStringValue(value.Transaction.Type); writer.WriteEndObject(); } @@ -39,10 +41,10 @@ public override void WriteJson(JsonWriter writer, MetricSet value, JsonSerialize writer.WriteStartObject(); writer.WritePropertyName("type"); - writer.WriteValue(value.Span.Type); + writer.WriteStringValue(value.Span.Type); writer.WritePropertyName("subtype"); - writer.WriteValue(value.Span.SubType); + writer.WriteStringValue(value.Span.SubType); writer.WriteEndObject(); } @@ -61,58 +63,56 @@ public override void WriteJson(JsonWriter writer, MetricSet value, JsonSerialize .Replace('"', '_')); writer.WriteStartObject(); writer.WritePropertyName("value"); - writer.WriteValue(item.KeyValue.Value); + writer.WriteNumberValue(item.KeyValue.Value); writer.WriteEndObject(); } } writer.WriteEndObject(); writer.WritePropertyName("timestamp"); - writer.WriteValue(value.Timestamp); + writer.WriteNumberValue(value.Timestamp); writer.WriteEndObject(); } - public override MetricSet ReadJson(JsonReader reader, Type objectType, MetricSet existingValue, bool hasExistingValue, - JsonSerializer serializer - ) + public override MetricSet Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (reader.TokenType == JsonToken.Null) + if (reader.TokenType == JsonTokenType.Null) return null; - if (reader.TokenType != JsonToken.StartObject) - throw new JsonReaderException($"Expected {JsonToken.StartObject} but found {reader.TokenType}"); + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException($"Expected {JsonTokenType.StartObject} but found {reader.TokenType}"); long timestamp = 0; var samples = new List(); while (reader.Read()) { - if (reader.TokenType == JsonToken.EndObject) + if (reader.TokenType == JsonTokenType.EndObject) break; - var property = (string)reader.Value; + var property = reader.GetString(); switch (property) { case "samples": reader.Read(); // { while (reader.Read()) { - if (reader.TokenType == JsonToken.EndObject) + if (reader.TokenType == JsonTokenType.EndObject) break; - var key = (string)reader.Value; + var key = reader.GetString(); double value = 0; reader.Read(); // { while (reader.Read()) { - if (reader.TokenType == JsonToken.EndObject) + if (reader.TokenType == JsonTokenType.EndObject) break; - var sampleValueProperty = (string)reader.Value; + var sampleValueProperty = reader.GetString(); if (sampleValueProperty == "value") { reader.Read(); - value = (double)reader.Value; + value = reader.GetDouble(); } } @@ -121,12 +121,13 @@ JsonSerializer serializer break; case "timestamp": reader.Read(); - timestamp = (long)reader.Value; + timestamp = reader.GetInt64(); break; } } return new MetricSet(timestamp, samples); } + } } diff --git a/src/Elastic.Apm/Report/Serialization/OutcomeConverter.cs b/src/Elastic.Apm/Report/Serialization/OutcomeConverter.cs deleted file mode 100644 index b6b62c2c9..000000000 --- a/src/Elastic.Apm/Report/Serialization/OutcomeConverter.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; - -namespace Elastic.Apm.Report.Serialization -{ - internal class OutcomeConverter : JsonConverter - { - public override Outcome ReadJson(JsonReader reader, Type objectType, Outcome existingValue, bool hasExistingValue, JsonSerializer serializer) - { - if (hasExistingValue) - return existingValue; - - while (reader.Read()) - { - if (reader.TokenType == JsonToken.EndObject) - break; - - if (reader.ValueType == typeof(string)) - { - var property = (string)reader.Value; - - if (Enum.TryParse(property, out var enumVal)) - return enumVal; - } - } - - return Outcome.Unknown; - } - public override void WriteJson(JsonWriter writer, Outcome value, JsonSerializer serializer) - { - - writer.WriteStartObject(); - writer.WriteValue(value.ToString().ToLower()); - writer.WriteEndObject(); - } - } -} diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index 4dc973813..17c892b59 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -2,65 +2,119 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System; +using System.Collections; +using System.ComponentModel; using System.Globalization; using System.IO; +using System.Linq; using System.Text; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using Elastic.Apm.Api; +using Elastic.Apm.Api.Constraints; +using Elastic.Apm.Model; -namespace Elastic.Apm.Report.Serialization + +namespace Elastic.Apm.Report.Serialization; + +[JsonSerializable(typeof(IntakeError))] +[JsonSerializable(typeof(IntakeResponse))] +internal partial class SourceGenerationContext : JsonSerializerContext +{ +} + +/// +/// Serializes payloads to send to APM server +/// +internal sealed class PayloadItemSerializer { + public JsonSerializerOptions Settings { get; } + + internal PayloadItemSerializer() => + Settings = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + WriteIndented = false, + Converters = { new JsonConverterDouble(), new JsonConverterDecimal() }, + TypeInfoResolver = JsonTypeInfoResolver.Combine(SourceGenerationContext.Default, new DefaultJsonTypeInfoResolver + { + Modifiers = { j => + { + foreach (var prop in j.Properties) + { + var maxLengthAttribute = prop.AttributeProvider.GetCustomAttributes(typeof(MaxLengthAttribute), false).FirstOrDefault() as MaxLengthAttribute; + if (maxLengthAttribute != null) + prop.CustomConverter = new TruncateJsonConverter(maxLengthAttribute.Length); + + if (prop.PropertyType == typeof(Lazy)) + prop.ShouldSerialize = (_, lazy) => (lazy as Lazy)?.IsValueCreated ?? false; + + else if ((j.Type == typeof(Transaction) || j.Type == typeof(ITransaction)) && prop.Name == "context") + prop.ShouldSerialize = (t, _) => (t as Transaction)?.ShouldSerializeContext() ?? false; + + else if ((j.Type == typeof(Span) || j.Type == typeof(ISpan)) && prop.Name == "context") + prop.ShouldSerialize = (s, _) => (s as Span)?.ShouldSerializeContext() ?? false; + + else if ((j.Type == typeof(Error) || j.Type == typeof(IError)) && prop.Name == "context") + prop.ShouldSerialize = (e, _) => (e as Error)?.ShouldSerializeContext() ?? false; + + else if (j.Type == typeof(Context) && prop.Name == "tags") + prop.ShouldSerialize = (e, _) => (e as Context)?.ShouldSerializeLabels() ?? false; + + else if (j.Type == typeof(Context) && prop.Name == "custom") + prop.ShouldSerialize = (e, _) => (e as Context)?.ShouldSerializeCustom() ?? false; + + else if (j.Type == typeof(SpanContext) && prop.Name == "tags") + prop.ShouldSerialize = (e, _) => (e as SpanContext)?.ShouldSerializeLabels() ?? false; + + else if (j.Type == typeof(Metadata) && prop.Name == "tags") + prop.ShouldSerialize = (e, _) => (e as Metadata)?.ShouldSerializeLabels() ?? false; + + else if (prop.PropertyType.GetInterfaces().Any(i => i == typeof(IDictionary))) + prop.ShouldSerialize = (_, dictionary) => ((dictionary as IDictionary)?.Count ?? 0) > 0; + + } + } + } + }), + }; + + public static PayloadItemSerializer Default { get; } = new(); + + public JsonTypeInfo GetTypeInfo(Type type) => Settings.TypeInfoResolver!.GetTypeInfo(type, Settings); + + public void Serialize(object item, StreamWriter writer) => + JsonSerializer.Serialize(writer.BaseStream, item, item.GetType(), Settings); + /// - /// Serializes payloads to send to APM server + /// Deserializes an instance of from JSON /// - internal sealed class PayloadItemSerializer + /// the JSON + /// the type to deserialize + /// a new instance of + internal T Deserialize(string json) { - private readonly JsonSerializer _serializer; + var val = JsonSerializer.Deserialize(json, Settings); + return val ?? default; + } - internal PayloadItemSerializer() - { - var settings = new JsonSerializerSettings - { - ContractResolver = new ElasticApmContractResolver(), - NullValueHandling = NullValueHandling.Ignore, - Formatting = Formatting.None, - }; - - _serializer = JsonSerializer.CreateDefault(settings); - } - - public void Serialize(object item, TextWriter writer) => _serializer.Serialize(writer, item); - - /// - /// Deserializes an instance of from JSON - /// - /// the JSON - /// the type to deserialize - /// a new instance of - internal T Deserialize(string json) - { - var val = _serializer.Deserialize(new JsonTextReader(new StringReader(json))); - return val ?? default; - } + internal T Deserialize(Stream stream) + { + var val = JsonSerializer.Deserialize(stream, Settings); + return val; + } - internal T Deserialize(Stream stream) - { - using var sr = new StreamReader(stream); - using var jsonTextReader = new JsonTextReader(sr); - var val = _serializer.Deserialize(jsonTextReader); - return val; - } - - /// - /// Serializes the item to JSON - /// - /// - /// - internal string Serialize(object item) - { - var builder = new StringBuilder(256); - using var writer = new StringWriter(builder, CultureInfo.InvariantCulture); - Serialize(item, writer); - return builder.ToString(); - } + /// + /// Serializes the item to JSON + /// + /// + /// + internal string Serialize(object item) + { + var bytes= JsonSerializer.SerializeToUtf8Bytes(item, item.GetType(), Settings); + return Encoding.UTF8.GetString(bytes); } } diff --git a/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs b/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs index f18f0d8ff..d39e55558 100644 --- a/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information using System; +using System.Text.Json; +using System.Text.Json.Serialization; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + namespace Elastic.Apm.Report.Serialization { @@ -21,10 +23,12 @@ public TruncateJsonConverter() : this(Consts.PropertyMaxLength) { } // ReSharper disable once MemberCanBePrivate.Global public TruncateJsonConverter(int maxLength) => MaxLength = maxLength; - public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer) => - writer.WriteValue(value.Truncate(MaxLength)); + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => + writer.WriteStringValue(value.Truncate(MaxLength)); + + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + reader.GetString(); + - public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer) => - reader.Value as string; } } diff --git a/src/Elastic.Apm/ServerInfo/ApmServerInfoProvider.cs b/src/Elastic.Apm/ServerInfo/ApmServerInfoProvider.cs index 820ac8fe8..528516637 100644 --- a/src/Elastic.Apm/ServerInfo/ApmServerInfoProvider.cs +++ b/src/Elastic.Apm/ServerInfo/ApmServerInfoProvider.cs @@ -4,15 +4,13 @@ // See the LICENSE file in the project root for more information using System; -using System.IO; using System.Net.Http; using System.Net.Http.Headers; -using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Elastic.Apm.Config; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Logging; +using Elastic.Apm.Report.Serialization; namespace Elastic.Apm.ServerInfo { @@ -33,13 +31,10 @@ internal static async Task FillApmServerInfo(IApmServerInfo apmServerInfo, IApmL if (responseMessage.IsSuccessStatusCode) { using var stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); - using var streamReader = new StreamReader(stream, Encoding.UTF8); - using var jsonReader = new JsonTextReader(streamReader); - var serializer = new JsonSerializer(); - var metadata = serializer.Deserialize(jsonReader); + var metadata = PayloadItemSerializer.Default.Deserialize(stream); var version = metadata?["version"]; - var strVersion = version?.Value(); + var strVersion = version?.GetValue(); if (strVersion != null) { try diff --git a/test/Elastic.Apm.Tests.MockApmServer/CompositeDto.cs b/test/Elastic.Apm.Tests.MockApmServer/CompositeDto.cs index e047210b2..cb92f313b 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/CompositeDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/CompositeDto.cs @@ -2,13 +2,14 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Apm.Libraries.Newtonsoft.Json; + +using System.Text.Json.Serialization; namespace Elastic.Apm.Tests.MockApmServer { public class CompositeDto { - [JsonProperty("compression_strategy")] + [JsonPropertyName("compression_strategy")] public string CompressionStrategy { get; set; } public int Count { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs b/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs index 56e722fa0..f281e6499 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs @@ -2,9 +2,10 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Model; // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -14,7 +15,7 @@ namespace Elastic.Apm.Tests.MockApmServer { internal class ContextDto : IDto { - [JsonProperty("tags")] + [JsonPropertyName("tags")] public LabelsDictionary Labels { get; set; } public Request Request { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs index 23a310ae0..8c3dc66b9 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs @@ -8,10 +8,12 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; + using Elastic.Apm.Logging; using Elastic.Apm.Specification; using Elastic.Apm.Tests.Utilities; @@ -19,6 +21,7 @@ using Microsoft.AspNetCore.Mvc; using NJsonSchema; using Xunit.Sdk; +using JsonSerializerOptions = System.Text.Json.JsonSerializerOptions; // ReSharper disable UnusedAutoPropertyAccessor.Local @@ -97,18 +100,15 @@ private async Task ParsePayload() private async Task ParsePayloadLineAndAddToReceivedData(string line) { var foundDto = false; - var payload = JsonConvert.DeserializeObject( + var payload = JsonSerializer.Deserialize( line, - new JsonSerializerSettings + new JsonSerializerOptions { - MissingMemberHandling = MissingMemberHandling.Error, - Error = (_, errorEventArgs) => - { - _logger.Error() - ?.Log("Failed to parse payload line as JSON. Error: {PayloadParsingErrorMessage}, line: `{PayloadLine}'", - errorEventArgs.ErrorContext.Error.Message, line); - } - }) ?? throw new ArgumentException("Deserialization failed"); + UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, + }); + + if (payload is null) + throw new ArgumentException("Deserialization failed"); await HandleParsed(nameof(payload.Error), payload.Error, _mockApmServer.ReceivedData.Errors, _mockApmServer.AddError); await HandleParsed(nameof(payload.Metadata), payload.Metadata, _mockApmServer.ReceivedData.Metadata, _mockApmServer.AddMetadata); @@ -139,10 +139,10 @@ async Task HandleParsed(string dtoType, TDto dto, ImmutableList accu }, _validator) .Value; - var jObject = JObject.Parse(line); - var value = jObject.GetValue(dtoType, StringComparison.OrdinalIgnoreCase); + var jObject = JsonNode.Parse(line) as JsonObject; + var value = jObject!.TryGetPropertyValue(dtoType, out var dtoValue) ? dtoValue.GetValue() : null; - var validationErrors = schema.Validate(value.ToString()); + var validationErrors = schema.Validate(value); validationErrors.Should().BeEmpty(); } @@ -189,7 +189,7 @@ private class PayloadLineDto public MetadataDto Metadata { get; set; } - [JsonProperty("metricset")] + [JsonPropertyName("metricset")] public MetricSetDto MetricSet { get; set; } public SpanDto Span { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/DroppedSpanStatsDto.cs b/test/Elastic.Apm.Tests.MockApmServer/DroppedSpanStatsDto.cs index afb5aa3de..a1f581f0e 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/DroppedSpanStatsDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/DroppedSpanStatsDto.cs @@ -2,20 +2,21 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; + namespace Elastic.Apm.Tests.MockApmServer { public class DroppedSpanStatsDto { - [JsonProperty("destination_service_resource")] + [JsonPropertyName("destination_service_resource")] public string DestinationServiceResource { get; } - [JsonProperty("duration.count")] + [JsonPropertyName("duration.count")] public int DurationCount { get; set; } - [JsonProperty("duration.sum.us")] + [JsonPropertyName("duration.sum.us")] public double DurationSumUs { get; set; } public Outcome Outcome { get; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/ErrorDto.cs b/test/Elastic.Apm.Tests.MockApmServer/ErrorDto.cs index 6ece4cd78..01759c030 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/ErrorDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/ErrorDto.cs @@ -2,9 +2,10 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using FluentAssertions; // ReSharper disable MemberCanBePrivate.Global @@ -23,17 +24,17 @@ internal class ErrorDto : ITimestampedDto public string Id { get; set; } - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } public long Timestamp { get; set; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } public TransactionDataDto Transaction { get; set; } - [JsonProperty("transaction_id")] + [JsonPropertyName("transaction_id")] public string TransactionId { get; set; } public override string ToString() => new ToStringBuilder(nameof(ErrorDto)) @@ -68,7 +69,7 @@ public void AssertValid() public class TransactionDataDto : IDto { - [JsonProperty("sampled")] + [JsonPropertyName("sampled")] public bool IsSampled { get; set; } public string Type { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs b/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs index 71fd6db72..295d8e046 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs @@ -2,7 +2,8 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Apm.Libraries.Newtonsoft.Json; + +using System.Text.Json.Serialization; namespace Elastic.Apm.Tests.MockApmServer; @@ -25,7 +26,7 @@ public class FaasDto public class TriggerDto { - [JsonProperty("request_id")] public string RequestId { get; set; } + [JsonPropertyName("request_id")] public string RequestId { get; set; } public string Type { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs b/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs index 7a3995d0c..2dc0d12fa 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs @@ -2,9 +2,10 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Model; // ReSharper disable MemberCanBePrivate.Global @@ -22,7 +23,7 @@ internal class SpanContextDto : IDto public Http Http { get; set; } - [JsonProperty("tags")] + [JsonPropertyName("tags")] public LabelsDictionary Labels { get; set; } public Message Message { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/SpanDto.cs b/test/Elastic.Apm.Tests.MockApmServer/SpanDto.cs index a5b370431..09025cac7 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/SpanDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/SpanDto.cs @@ -3,9 +3,10 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Model; // ReSharper disable MemberCanBePrivate.Global @@ -25,13 +26,13 @@ internal class SpanDto : ITimedDto public Outcome Outcome { get; set; } - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } - [JsonProperty("sample_rate")] + [JsonPropertyName("sample_rate")] public string SampleRate { get; set; } - [JsonProperty("stacktrace")] + [JsonPropertyName("stacktrace")] public List StackTrace { get; set; } public List Links { get; set; } @@ -42,10 +43,10 @@ internal class SpanDto : ITimedDto public long Timestamp { get; set; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } - [JsonProperty("transaction_id")] + [JsonPropertyName("transaction_id")] public string TransactionId { get; set; } public string Type { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/SpanLinkDto.cs b/test/Elastic.Apm.Tests.MockApmServer/SpanLinkDto.cs index 51489b603..b06b6ce1f 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/SpanLinkDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/SpanLinkDto.cs @@ -3,15 +3,16 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Apm.Libraries.Newtonsoft.Json; + +using System.Text.Json.Serialization; namespace Elastic.Apm.Tests.MockApmServer; internal class SpanLinkDto { - [JsonProperty("span_id")] + [JsonPropertyName("span_id")] public string SpanId { get; set; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } } diff --git a/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs b/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs index 1d7d533ea..bdaa9aeb1 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs @@ -3,9 +3,10 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using FluentAssertions; // ReSharper disable MemberCanBePrivate.Global @@ -20,33 +21,33 @@ internal class TransactionDto : ITimedDto public double Duration { get; set; } public string Id { get; set; } - [JsonProperty("sampled")] + [JsonPropertyName("sampled")] public bool IsSampled { get; set; } public string Name { get; set; } public Outcome Outcome { get; set; } - [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] public string ParentId { get; set; } public string Result { get; set; } - [JsonProperty("sample_rate")] + [JsonPropertyName("sample_rate")] public string SampleRate { get; set; } - [JsonProperty("span_count")] + [JsonPropertyName("span_count")] public SpanCountDto SpanCount { get; set; } public long Timestamp { get; set; } - [JsonProperty("trace_id")] + [JsonPropertyName("trace_id")] public string TraceId { get; set; } public string Type { get; set; } - [JsonProperty("dropped_spans_stats")] + [JsonPropertyName("dropped_spans_stats")] public List DroppedSpanStats { get; set; } public FaasDto FaaS { get; set; } diff --git a/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs b/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs index e73eaa5f7..1a242c411 100644 --- a/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs +++ b/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs @@ -8,7 +8,8 @@ using System.IO; using System.Linq; using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using Xunit.Sdk; namespace Elastic.Apm.Tests.Utilities; @@ -36,20 +37,23 @@ public override IEnumerable GetData(MethodInfo testMethod) if (!File.Exists(_fileName)) throw new ArgumentException($"JSON input file {_fileName} does not exist"); - var jToken = JToken.Parse(File.ReadAllText(_fileName), new JsonLoadSettings + var jToken = JsonNode.Parse(File.ReadAllText(_fileName), new JsonNodeOptions(), new JsonDocumentOptions { - CommentHandling = CommentHandling.Ignore + CommentHandling = JsonCommentHandling.Skip }); - - foreach (var kvp in (JObject)jToken) + if (jToken is JsonObject jObject) { - var name = kvp.Key; - var data = ParseTestData(kvp.Value as JObject); - yield return [name, data]; + foreach (var kvp in jObject) + { + var name = kvp.Key; + var data = ParseTestData(kvp.Value as JsonObject); + yield return [name, data]; + } } + } - private static CGroupTestData ParseTestData(JObject jToken) + private static CGroupTestData ParseTestData(JsonObject jToken) { var testData = new CGroupTestData { Files = new CgroupFiles() }; @@ -58,18 +62,18 @@ private static CGroupTestData ParseTestData(JObject jToken) switch (kvp.Key) { case "containerId": - testData.ContainerId = kvp.Value?.Value(); + testData.ContainerId = kvp.Value?.GetValue(); break; case "podId": - testData.PodId = kvp.Value?.Value(); + testData.PodId = kvp.Value?.GetValue(); break; case "files": - var o = (JObject)kvp.Value; - var cgroupA = o.Property("/proc/self/cgroup")?.Value as JArray; - testData.Files.ProcSelfCgroup = cgroupA?.Values().FirstOrDefault(); + var o = (JsonObject)kvp.Value; + var cgroupA = o.TryGetPropertyValue("/proc/self/cgroup", out var cgroup) ? cgroup as JsonArray : null; + testData.Files.ProcSelfCgroup = cgroupA?.GetValues().FirstOrDefault(); - var mountInfoA = o.Property("/proc/self/mountinfo")?.Value as JArray; - testData.Files.MountInfo = mountInfoA?.Values().ToArray(); + var mountInfoA = o.TryGetPropertyValue("/proc/self/mountinfo", out var mountinfo) ? mountinfo as JsonArray : null; + testData.Files.MountInfo = mountInfoA?.GetValues().ToArray(); break; } } diff --git a/test/Elastic.Apm.Tests.Utilities/JsonFileDataAttribute.cs b/test/Elastic.Apm.Tests.Utilities/JsonFileDataAttribute.cs index 3698d3530..b2845fbe0 100644 --- a/test/Elastic.Apm.Tests.Utilities/JsonFileDataAttribute.cs +++ b/test/Elastic.Apm.Tests.Utilities/JsonFileDataAttribute.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using System.IO; using System.Reflection; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; +using Elastic.Apm.Report.Serialization; using Xunit.Sdk; namespace Elastic.Apm.Tests.Utilities; @@ -19,7 +21,7 @@ public class JsonFileDataAttribute : DataAttribute public JsonFileDataAttribute(string fileName, Type inputDataType = null) { _fileName = fileName; - _inputDataType = inputDataType ?? typeof(JToken); + _inputDataType = inputDataType ?? typeof(JsonObject); } public override IEnumerable GetData(MethodInfo testMethod) @@ -27,19 +29,19 @@ public override IEnumerable GetData(MethodInfo testMethod) if (!File.Exists(_fileName)) throw new ArgumentException($"JSON input file {_fileName} does not exist"); - var jToken = JToken.Parse(File.ReadAllText(_fileName), new JsonLoadSettings + var jToken = JsonNode.Parse(File.ReadAllText(_fileName), new JsonNodeOptions(), new JsonDocumentOptions { - CommentHandling = CommentHandling.Ignore + CommentHandling = JsonCommentHandling.Skip }); - switch (jToken.Type) + switch (jToken) { - case JTokenType.Array: - foreach (var t in jToken) - yield return new[] { t.ToObject(_inputDataType) }; + case JsonArray jsonArray: + foreach (var t in jsonArray) + yield return [t.Deserialize(_inputDataType, PayloadItemSerializer.Default.Settings)]; break; - case JTokenType.Object: - foreach (var kvp in (JObject)jToken) - yield return new[] { kvp.Key, kvp.Value.ToObject(_inputDataType) }; + case JsonObject jsonObject: + foreach (var kvp in jsonObject) + yield return [kvp.Key, kvp.Value.Deserialize(_inputDataType, PayloadItemSerializer.Default.Settings)]; break; default: throw new Exception($"Unexpected JSON input: '{jToken}'"); diff --git a/test/Elastic.Apm.Tests.Utilities/JsonUtils.cs b/test/Elastic.Apm.Tests.Utilities/JsonUtils.cs index 392f0db80..2e21369a4 100644 --- a/test/Elastic.Apm.Tests.Utilities/JsonUtils.cs +++ b/test/Elastic.Apm.Tests.Utilities/JsonUtils.cs @@ -2,27 +2,27 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using System.Globalization; using System.IO; -using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; -namespace Elastic.Apm.Tests.Utilities +namespace Elastic.Apm.Tests.Utilities; + +public static class JsonUtils { - public static class JsonUtils + public static string PrettyFormat(this string inputJson) { - public static string PrettyFormat(this string inputJson) + var node = JsonNode.Parse(inputJson); + + using var stream = new MemoryStream(); + using var jsonTextWriter = new Utf8JsonWriter(stream); + node?.WriteTo(jsonTextWriter, new JsonSerializerOptions { - using var stringWriter = new StringWriter(CultureInfo.InvariantCulture); - using var jsonTextWriter = new JsonTextWriter(stringWriter) - { - Formatting = Formatting.Indented, - Indentation = TextUtils.IndentationLength, - IndentChar = TextUtils.IndentationChar - }; - JToken.Parse(inputJson).WriteTo(jsonTextWriter); - return stringWriter.ToString(); - } + WriteIndented = true + }); + + return Encoding.UTF8.GetString(stream.ToArray()); + } } diff --git a/test/Elastic.Apm.Tests.Utilities/MockPayloadSender.cs b/test/Elastic.Apm.Tests.Utilities/MockPayloadSender.cs index 01df74d34..8e4208cc0 100644 --- a/test/Elastic.Apm.Tests.Utilities/MockPayloadSender.cs +++ b/test/Elastic.Apm.Tests.Utilities/MockPayloadSender.cs @@ -8,9 +8,9 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Text.Json.Nodes; using System.Threading; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Logging; using Elastic.Apm.Metrics; using Elastic.Apm.Model; @@ -21,8 +21,9 @@ namespace Elastic.Apm.Tests.Utilities { internal class MockPayloadSender : IPayloadSender, IPayloadSenderWithFilters { - private static readonly JObject JsonSpanTypesData = - JObject.Parse(File.ReadAllText(Path.Combine(SolutionPaths.Root, "test/Elastic.Apm.Tests.Utilities/TestResources/json-specs/span_types.json"))); + private static readonly JsonObject JsonSpanTypesData = + JsonNode.Parse(File.ReadAllText(Path.Combine(SolutionPaths.Root, "test/Elastic.Apm.Tests.Utilities/TestResources/json-specs/span_types.json"))) + as JsonObject; private readonly List _errors = []; private readonly List> _errorFilters = []; @@ -277,12 +278,12 @@ private void VerifySpan(ISpan span) if (IsStrictSpanCheckEnabled) { - var spanTypeInfo = JsonSpanTypesData[type] as JObject; + var spanTypeInfo = JsonSpanTypesData[type] as JsonObject; spanTypeInfo.Should().NotBeNull($"span type '{type}' is not allowed by the spec"); - var allowNullSubtype = spanTypeInfo["allow_null_subtype"]?.Value(); - var allowUnlistedSubtype = spanTypeInfo["allow_unlisted_subtype"]?.Value(); - var subTypes = spanTypeInfo["subtypes"]; + var allowNullSubtype = spanTypeInfo["allow_null_subtype"]?.GetValue(); + var allowUnlistedSubtype = spanTypeInfo["allow_unlisted_subtype"]?.GetValue(); + var subTypes = spanTypeInfo["subtypes"] as JsonObject; var hasSubtypes = subTypes != null && subTypes.Any(); var subType = span.Subtype; diff --git a/test/Elastic.Apm.Tests/ApiTests/ApiTests.cs b/test/Elastic.Apm.Tests/ApiTests/ApiTests.cs index a44e1dbd5..2e0f7dd85 100644 --- a/test/Elastic.Apm.Tests/ApiTests/ApiTests.cs +++ b/test/Elastic.Apm.Tests/ApiTests/ApiTests.cs @@ -509,12 +509,12 @@ public void LabelsOnTransactionAndSpan() payloadSender.Errors.Should().ContainSingle(); payloadSender.FirstError.Exception.Message.Should().Be(exceptionMessage); - payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["fooTransaction1"].Value.Should().Be("barTransaction1"); - payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["fooTransaction2"].Value.Should().Be("barTransaction2"); + payloadSender.FirstTransaction.Context.InternalLabels.MergedDictionary["fooTransaction1"].Value.Should().Be("barTransaction1"); + payloadSender.FirstTransaction.Context.InternalLabels.MergedDictionary["fooTransaction2"].Value.Should().Be("barTransaction2"); payloadSender.WaitForSpans(); - payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["fooSpan1"].Value.Should().Be("barSpan1"); - payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["fooSpan2"].Value.Should().Be("barSpan2"); + payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.MergedDictionary["fooSpan1"].Value.Should().Be("barSpan1"); + payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.MergedDictionary["fooSpan2"].Value.Should().Be("barSpan2"); } /// @@ -599,9 +599,9 @@ public void SubSpanWithLabels() var payloadSender = new MockPayloadSender(); StartTransactionAndSpanWithSubSpan(payloadSender, span2 => { span2.SetLabel("foo", 42); }); - payloadSender.FirstSpan.Context.InternalLabels.Value.MergedDictionary.Should().NotBeEmpty(); - payloadSender.FirstSpan.Context.InternalLabels.Value.MergedDictionary.Should().ContainKey("foo"); - payloadSender.FirstSpan.Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be(42); + payloadSender.FirstSpan.Context.InternalLabels.MergedDictionary.Should().NotBeEmpty(); + payloadSender.FirstSpan.Context.InternalLabels.MergedDictionary.Should().ContainKey("foo"); + payloadSender.FirstSpan.Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be(42); } /// @@ -712,9 +712,9 @@ public void ErrorShouldContainTransactionData(bool isSampled, bool captureOnSpan { var payloadSender = new MockPayloadSender(); var expectedErrorContext = new Context(); - expectedErrorContext.InternalLabels.Value.InnerDictionary["one"] = 1; - expectedErrorContext.InternalLabels.Value.InnerDictionary["twenty two"] = "22"; - expectedErrorContext.InternalLabels.Value.InnerDictionary["true"] = true; + expectedErrorContext.InternalLabels.InnerDictionary["one"] = 1; + expectedErrorContext.InternalLabels.InnerDictionary["twenty two"] = "22"; + expectedErrorContext.InternalLabels.InnerDictionary["true"] = true; ITransaction capturedTransaction = null; IExecutionSegment errorCapturingExecutionSegment = null; @@ -724,8 +724,8 @@ public void ErrorShouldContainTransactionData(bool isSampled, bool captureOnSpan agent.Tracer.CaptureTransaction(TestTransaction, CustomTransactionTypeForTests, transaction => { capturedTransaction = transaction; - foreach (var item in expectedErrorContext.InternalLabels.Value.MergedDictionary) - transaction.Context.InternalLabels.Value.MergedDictionary[item.Key] = item.Value; + foreach (var item in expectedErrorContext.InternalLabels.MergedDictionary) + transaction.Context.InternalLabels.MergedDictionary[item.Key] = item.Value; ISpan span = null; if (captureOnSpan) { diff --git a/test/Elastic.Apm.Tests/ApiTests/ConvenientApiSpanTests.cs b/test/Elastic.Apm.Tests/ApiTests/ConvenientApiSpanTests.cs index 16ab2abd9..9b019814e 100644 --- a/test/Elastic.Apm.Tests/ApiTests/ConvenientApiSpanTests.cs +++ b/test/Elastic.Apm.Tests/ApiTests/ConvenientApiSpanTests.cs @@ -639,7 +639,7 @@ public void LabelsOnSpan() }); //According to the Intake API labels are stored on the Context (and not on Spans.Labels directly). - payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); + payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.InnerDictionary["foo"].Value.Should().Be("bar"); } /// @@ -660,7 +660,7 @@ await t.CaptureSpan(SpanName, SpanType, async span => }); //According to the Intake API labels are stored on the Context (and not on Spans.Labels directly). - payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be("bar"); + payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be("bar"); } /// @@ -687,7 +687,7 @@ await t.CaptureSpan(SpanName, SpanType, async span => }); //According to the Intake API labels are stored on the Context (and not on Spans.Labels directly). - payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be("bar"); + payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be("bar"); } /// diff --git a/test/Elastic.Apm.Tests/ApiTests/ConvenientApiTransactionTests.cs b/test/Elastic.Apm.Tests/ApiTests/ConvenientApiTransactionTests.cs index 74b5fc923..0919537b1 100644 --- a/test/Elastic.Apm.Tests/ApiTests/ConvenientApiTransactionTests.cs +++ b/test/Elastic.Apm.Tests/ApiTests/ConvenientApiTransactionTests.cs @@ -435,7 +435,7 @@ public void LabelsOnTransaction() }); //According to the Intake API labels are stored on the Context (and not on Transaction.Labels directly). - payloadSender.FirstTransaction.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); + payloadSender.FirstTransaction.Context.InternalLabels.InnerDictionary["foo"].Value.Should().Be("bar"); } /// @@ -456,7 +456,7 @@ await t.Tracer.CaptureTransaction(TransactionName, TransactionType, async transa }); //According to the Intake API labels are stored on the Context (and not on Transaction.Labels directly). - payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be("bar"); + payloadSender.FirstTransaction.Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be("bar"); } /// @@ -484,7 +484,7 @@ await t.Tracer.CaptureTransaction(TransactionName, TransactionType, async transa }); //According to the Intake API labels are stored on the Context (and not on Transaction.Labels directly). - payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be("bar"); + payloadSender.FirstTransaction.Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be("bar"); } /// diff --git a/test/Elastic.Apm.Tests/DbSpanNameTests.cs b/test/Elastic.Apm.Tests/DbSpanNameTests.cs index 480bd045d..bfdbc9a1c 100644 --- a/test/Elastic.Apm.Tests/DbSpanNameTests.cs +++ b/test/Elastic.Apm.Tests/DbSpanNameTests.cs @@ -16,8 +16,8 @@ public class DbSpanNameTests { public struct SqlSignatureTestData { - public string Input; - public string Output; + public string Input { get; set; } + public string Output { get; set; } } [Theory] @@ -33,16 +33,17 @@ public void TestDbSignatures(SqlSignatureTestData data) public class SqlTokenTestData { - public string Name; - public string Comment; - public string Input; - public List Tokens = new(); + public string Name { get; set; } + public string Comment { get; set; } + public string Input { get; set; } + public List Tokens { get; set; } = new(); + } public struct SqlToken { - public string Kind; - public string Text; + public string Kind { get; set; } + public string Text { get; set; } } [Theory] diff --git a/test/Elastic.Apm.Tests/DistributedTracing/BaggageTests.cs b/test/Elastic.Apm.Tests/DistributedTracing/BaggageTests.cs index 07654abfe..80365f546 100644 --- a/test/Elastic.Apm.Tests/DistributedTracing/BaggageTests.cs +++ b/test/Elastic.Apm.Tests/DistributedTracing/BaggageTests.cs @@ -50,7 +50,7 @@ public void CaptureBaggageWithDefaultConfig() payloadSender.FirstError.Should().NotBeNull(); payloadSender.FirstError.Context.InternalLabels.Should().NotBeNull(); - payloadSender.FirstError.Context.InternalLabels.Value.Should().Contain(new KeyValuePair("baggage.foo", "bar")); + payloadSender.FirstError.Context.InternalLabels.Should().Contain(new KeyValuePair("baggage.foo", "bar")); } /// @@ -79,10 +79,10 @@ public void CaptureBaggageWithNonDefaultConfig() payloadSender.FirstError.Should().NotBeNull(); payloadSender.FirstError.Context.InternalLabels.Should().NotBeNull(); - payloadSender.FirstError.Context.InternalLabels.Value.Should().Contain(new KeyValuePair("baggage.foo", "bar")); - payloadSender.FirstError.Context.InternalLabels.Value.Should().NotContainKey("key1"); - payloadSender.FirstError.Context.InternalLabels.Value.Should().NotContainKey("foo"); - payloadSender.FirstError.Context.InternalLabels.Value.Should().NotContainKey("baggage.key1"); + payloadSender.FirstError.Context.InternalLabels.Should().Contain(new KeyValuePair("baggage.foo", "bar")); + payloadSender.FirstError.Context.InternalLabels.Should().NotContainKey("key1"); + payloadSender.FirstError.Context.InternalLabels.Should().NotContainKey("foo"); + payloadSender.FirstError.Context.InternalLabels.Should().NotContainKey("baggage.key1"); } private void RunSample(ApmAgent agent) diff --git a/test/Elastic.Apm.Tests/DistributedTracing/DistributedTracingTests.cs b/test/Elastic.Apm.Tests/DistributedTracing/DistributedTracingTests.cs index f5469a9fe..70b07d547 100644 --- a/test/Elastic.Apm.Tests/DistributedTracing/DistributedTracingTests.cs +++ b/test/Elastic.Apm.Tests/DistributedTracing/DistributedTracingTests.cs @@ -5,8 +5,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json.Serialization; using Elastic.Apm.DistributedTracing; -using Elastic.Apm.Libraries.Newtonsoft.Json; + using Elastic.Apm.Tests.Utilities; using FluentAssertions; using Xunit; @@ -18,8 +19,12 @@ public class DistributedTracingTests public class TraceStateTestData { public List Headers { get; set; } - [JsonProperty("is_traceparent_valid")] public bool IsTraceParentValid { get; set; } - [JsonProperty("is_tracestate_valid")] public bool? IsTraceStateValid { get; set; } + + [JsonPropertyName("is_traceparent_valid")] + public bool IsTraceParentValid { get; set; } + + [JsonPropertyName("is_tracestate_valid")] + public bool? IsTraceStateValid { get; set; } } [Theory] diff --git a/test/Elastic.Apm.Tests/ErrorTests.cs b/test/Elastic.Apm.Tests/ErrorTests.cs index 47040ca00..6de485257 100644 --- a/test/Elastic.Apm.Tests/ErrorTests.cs +++ b/test/Elastic.Apm.Tests/ErrorTests.cs @@ -50,7 +50,7 @@ public void ChangeTransactionContextAfterError() t.Context.Request.Url.Search = "cde"; t.Context.Response.StatusCode = 500; t.Context.Response.Finished = true; - t.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); + t.Context.InternalLabels.InnerDictionary["foo"].Value.Should().Be("bar"); // Asserts on the captured error mockPayloadSender.WaitForErrors(); @@ -65,7 +65,7 @@ public void ChangeTransactionContextAfterError() mockPayloadSender.FirstError.Context.Request.Url.Search.Should().Be("abc"); mockPayloadSender.FirstError.Context.Response.StatusCode.Should().Be(404); mockPayloadSender.FirstError.Context.Response.Finished.Should().BeFalse(); - mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); + mockPayloadSender.FirstError.Context.InternalLabels.InnerDictionary["foo"].Value.Should().Be("bar"); mockPayloadSender.FirstError.Context.Response.Headers.Should().BeNull(); }); @@ -81,7 +81,7 @@ public void ChangeTransactionContextAfterError() mockPayloadSender.FirstTransaction.Context.Request.Url.Search.Should().Be("cde"); mockPayloadSender.FirstTransaction.Context.Response.StatusCode.Should().Be(500); mockPayloadSender.FirstTransaction.Context.Response.Finished.Should().BeTrue(); - mockPayloadSender.FirstTransaction.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); + mockPayloadSender.FirstTransaction.Context.InternalLabels.InnerDictionary["foo"].Value.Should().Be("bar"); mockPayloadSender.FirstTransaction.Context.Response.Headers.Should().BeNull(); } @@ -131,7 +131,7 @@ public void ErrorOnTransactionWithEmptyHeaders() mockPayloadSender.FirstError.Context.Request.Headers.Should().BeNull(); mockPayloadSender.FirstError.Context.Response.Should().NotBeNull(); mockPayloadSender.FirstError.Context.Response.Headers.Should().BeNull(); - mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary.Should().BeEmpty(); + mockPayloadSender.FirstError.Context.InternalLabels.InnerDictionary.Should().BeEmpty(); } [Fact] diff --git a/test/Elastic.Apm.Tests/FilterTests.cs b/test/Elastic.Apm.Tests/FilterTests.cs index 8de289b30..e63dcd14d 100644 --- a/test/Elastic.Apm.Tests/FilterTests.cs +++ b/test/Elastic.Apm.Tests/FilterTests.cs @@ -8,11 +8,13 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; using System.Threading; using System.Threading.Tasks; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; + using Elastic.Apm.Logging; using Elastic.Apm.Model; using Elastic.Apm.Report; @@ -262,21 +264,21 @@ Action, List, List> assert foreach (var receivedEvent in payloadStrings) { - var jObject = JObject.Parse(receivedEvent); - var property = jObject.Properties().First(); + var jObject = JsonDocument.Parse(receivedEvent); + var property = jObject.RootElement.EnumerateObject().First(); switch (property.Name) { case "transaction": - var transaction = serializer.Deserialize(property.Value.ToString(Formatting.None)); + var transaction = serializer.Deserialize(property.Value.ToString()); transactions.Add(transaction); break; case "span": - var span = serializer.Deserialize(property.Value.ToString(Formatting.None)); + var span = serializer.Deserialize(property.Value.ToString()); spans.Add(span); break; case "error": - var error = serializer.Deserialize(property.Value.ToString(Formatting.None)); + var error = serializer.Deserialize(property.Value.ToString()); errors.Add(error); break; } diff --git a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs index cd137ba8a..b8c7f8e33 100644 --- a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs +++ b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs @@ -26,17 +26,17 @@ public void RuntimeName() switch (RuntimeInformation.FrameworkDescription) { case { } str when str.StartsWith(Runtime.MonoName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Service.Runtime.Name.Should().Be(Runtime.MonoName); + mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.MonoName); break; case { } str when str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); + mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); break; case { } str when str.StartsWith(Runtime.DotNetCoreName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); + mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); break; case { } str when str.StartsWith(Runtime.DotNetName, StringComparison.OrdinalIgnoreCase) && !str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); + mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); break; } } diff --git a/test/Elastic.Apm.Tests/LabelTests.cs b/test/Elastic.Apm.Tests/LabelTests.cs index 59b399272..9670ece46 100644 --- a/test/Elastic.Apm.Tests/LabelTests.cs +++ b/test/Elastic.Apm.Tests/LabelTests.cs @@ -18,10 +18,7 @@ namespace Elastic.Apm.Tests { public class LabelTests { - private readonly PayloadItemSerializer _payloadItemSerializer; - - public LabelTests() => - _payloadItemSerializer = new PayloadItemSerializer(); + private readonly PayloadItemSerializer _payloadItemSerializer = PayloadItemSerializer.Default; [InlineData("StrValue")] [InlineData(123)] @@ -40,7 +37,7 @@ public void SingleLabelOnTransactionTests(object labelValue) agent.Tracer.CaptureTransaction("test", "test", t => { SetLabel(t, labelValue, labelName); - t.Context.InternalLabels.Value.InnerDictionary[labelName].Value.Should().Be(labelValue); + t.Context.InternalLabels.InnerDictionary[labelName].Value.Should().Be(labelValue); transaction = t; }); @@ -68,7 +65,7 @@ public void SingleLabelOnSpanTests(object labelValue) { span = s; SetLabel(s, labelValue, labelName); - s.Context.InternalLabels.Value.InnerDictionary[labelName].Value.Should().Be(labelValue); + s.Context.InternalLabels.InnerDictionary[labelName].Value.Should().Be(labelValue); }); }); @@ -110,18 +107,18 @@ public void MultipleLabelsTest() SetLabel(s, "abc", "stringLabel"); SetLabel(s, true, "boolLabel"); - s.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(1); - s.Context.InternalLabels.Value.InnerDictionary["stringLabel"].Value.Should().Be("abc"); - s.Context.InternalLabels.Value.InnerDictionary["boolLabel"].Value.Should().Be(true); + s.Context.InternalLabels.InnerDictionary["intLabel"].Value.Should().Be(1); + s.Context.InternalLabels.InnerDictionary["stringLabel"].Value.Should().Be("abc"); + s.Context.InternalLabels.InnerDictionary["boolLabel"].Value.Should().Be(true); }); SetLabel(t, 1, "intLabel"); SetLabel(t, "abc", "stringLabel"); SetLabel(t, true, "boolLabel"); - t.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(1); - t.Context.InternalLabels.Value.InnerDictionary["stringLabel"].Value.Should().Be("abc"); - t.Context.InternalLabels.Value.InnerDictionary["boolLabel"].Value.Should().Be(true); + t.Context.InternalLabels.InnerDictionary["intLabel"].Value.Should().Be(1); + t.Context.InternalLabels.InnerDictionary["stringLabel"].Value.Should().Be("abc"); + t.Context.InternalLabels.InnerDictionary["boolLabel"].Value.Should().Be(true); }); var transactionJsonString = _payloadItemSerializer.Serialize(transaction); @@ -146,9 +143,9 @@ public void LabelsOnErrorTest() // add label to transaction after the error - error does not contain this t.SetLabel("boolLabel", true); - mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(5); - mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary["stringLabel"].Value.Should().Be("test"); - mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary.Should().NotContainKey("boolLabel"); + mockPayloadSender.FirstError.Context.InternalLabels.InnerDictionary["intLabel"].Value.Should().Be(5); + mockPayloadSender.FirstError.Context.InternalLabels.InnerDictionary["stringLabel"].Value.Should().Be("test"); + mockPayloadSender.FirstError.Context.InternalLabels.InnerDictionary.Should().NotContainKey("boolLabel"); }); } @@ -164,7 +161,7 @@ public void SameLabelTwice() t.SetLabel("intLabel", 6); }); - mockPayloadSender.FirstTransaction.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(6); + mockPayloadSender.FirstTransaction.Context.InternalLabels.InnerDictionary["intLabel"].Value.Should().Be(6); } #pragma warning disable CS0618 // Type or member is obsolete //For testing backwards compatibility we also test the obsolete Dictionary Labels property here. @@ -181,13 +178,13 @@ public void PublicStringDictionaryPropertySerializationTest() { transaction = t; t.Labels["foo1"] = "bar1"; - t.Context.InternalLabels.Value.MergedDictionary["foo1"].Value.Should().Be("bar1"); + t.Context.InternalLabels.MergedDictionary["foo1"].Value.Should().Be("bar1"); t.CaptureSpan("testSpan", "test", s => { span = s; s.Labels["foo2"] = "bar2"; - s.Context.InternalLabels.Value.MergedDictionary["foo2"].Value.Should().Be("bar2"); + s.Context.InternalLabels.MergedDictionary["foo2"].Value.Should().Be("bar2"); }); }); @@ -212,13 +209,13 @@ public void PublicStringDictionaryPropertyInSyncTest() transaction.Labels.Keys.Should().HaveCount(1); transaction.Labels.Keys.First().Should().Be("foo"); - transaction.Context.InternalLabels.Value.MergedDictionary["foo"].Value.Should().Be("bar"); + transaction.Context.InternalLabels.MergedDictionary["foo"].Value.Should().Be("bar"); transaction.SetLabel("item2", 123); //assert that the string API still only contains 1 item: transaction.Labels.Should().HaveCount(1); - transaction.Context.InternalLabels.Value.MergedDictionary.Keys.Should().HaveCount(2); + transaction.Context.InternalLabels.MergedDictionary.Keys.Should().HaveCount(2); foreach (var item in transaction.Labels) { @@ -381,8 +378,8 @@ private static string GetAssertString(object labelValue, string labelName) serializedStrPattern += boolVal.ToString().ToLower(); else if (labelValue is double doubleValToStr) serializedStrPattern += string.Format(CultureInfo.InvariantCulture, "{0:N1}", doubleValToStr); - else if (labelValue is decimal dedimalValToStr) - serializedStrPattern += string.Format(CultureInfo.InvariantCulture, "{0:N1}", dedimalValToStr); + else if (labelValue is decimal decimalVal) + serializedStrPattern += string.Format(CultureInfo.InvariantCulture, "{0:N1}", decimalVal); else serializedStrPattern += labelValue; diff --git a/test/Elastic.Apm.Tests/SerializationTests.cs b/test/Elastic.Apm.Tests/SerializationTests.cs index d24381168..77e4a0973 100644 --- a/test/Elastic.Apm.Tests/SerializationTests.cs +++ b/test/Elastic.Apm.Tests/SerializationTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text.Json.Nodes; using Elastic.Apm.Api; using Elastic.Apm.Api.Constraints; using Elastic.Apm.Helpers; @@ -66,7 +67,7 @@ public void StringTruncationTest() } /// - /// It creates an instance of with a that has a string + /// It creates an instance of with a that has a string /// which is longer than . /// Makes sure that the serialized instance still contains the whole string (aka it was not trimmed), since /// the property pointing to the string wasn't marked with any attributes, so it's not trimmed. @@ -76,14 +77,14 @@ public void StringNoTruncateAttributeTest() { var str = new string('a', 1200); - var dummyInstance = new DummyType { IntProp = 42, StringProp = str }; + var dummyInstance = new DummyType { Int = 42, Str = str }; var json = _payloadItemSerializer.Serialize(dummyInstance); var deserializedDummyInstance = JsonConvert.DeserializeObject(json); deserializedDummyInstance.Should().NotBeNull(); - deserializedDummyInstance.StringProp.Should().Be(str); - deserializedDummyInstance.IntProp.Should().Be(42); + deserializedDummyInstance.Str.Should().Be(str); + deserializedDummyInstance.Int.Should().Be(42); } /// @@ -97,7 +98,7 @@ public void LabelsTruncation() var str = new string('a', 1200); var context = new Context(); - context.InternalLabels.Value.InnerDictionary["foo"] = str; + context.InternalLabels.InnerDictionary["foo"] = str; var json = _payloadItemSerializer.Serialize(context); var deserializedContext = JsonConvert.DeserializeObject(json); @@ -127,9 +128,10 @@ public void LabelsTruncationSpanContext() var str = new string('a', 1200); var context = new SpanContext(); - context.InternalLabels.Value.InnerDictionary["foo"] = str; + context.InternalLabels.InnerDictionary["foo"] = str; var json = _payloadItemSerializer.Serialize(context); + json.Should().Contain("tags"); var deserializedContext = JsonConvert.DeserializeObject(json); deserializedContext.Should().NotBeNull(); @@ -153,7 +155,7 @@ public void LabelsTruncationSpanContext() public void LabelWithNullValueShouldBeCaptured() { var context = new SpanContext(); - context.InternalLabels.Value.InnerDictionary["foo"] = null; + context.InternalLabels.InnerDictionary["foo"] = null; var json = _payloadItemSerializer.Serialize(context); var deserializedContext = JsonConvert.DeserializeObject(json); @@ -169,7 +171,7 @@ public void LabelWithNullValueShouldBeCaptured() public void LabelWithEmptyStringShouldBeCaptured() { var context = new SpanContext(); - context.InternalLabels.Value.InnerDictionary["foo"] = string.Empty; + context.InternalLabels.InnerDictionary["foo"] = string.Empty; var json = _payloadItemSerializer.Serialize(context); var deserializedContext = JsonConvert.DeserializeObject(json); @@ -179,7 +181,7 @@ public void LabelWithEmptyStringShouldBeCaptured() } /// - /// It creates an instance of with a that has a value + /// It creates an instance of with a that has a value /// which is longer than . /// Makes sure that the serialized instance still contains the whole value (aka it was not trimmed), since /// the property pointing to the string is not marked with any attributes, so it is not trimmed. @@ -190,13 +192,13 @@ public void DictionaryNoTruncateAttributeTest() var str = new string('a', 1200); var dummyInstance = new DummyType(); - dummyInstance.DictionaryProp["foo"] = str; + dummyInstance.Dict["foo"] = str; var json = _payloadItemSerializer.Serialize(dummyInstance); - var deserializedDummyInstance = JsonConvert.DeserializeObject(json); + var deserializedDummyInstance = _payloadItemSerializer.Deserialize(json); deserializedDummyInstance.Should().NotBeNull(); - deserializedDummyInstance["dictionaryProp"]["foo"].Value().Should().Be(str); + deserializedDummyInstance["dict"]["foo"].GetValue().Should().Be(str); } /// @@ -280,19 +282,19 @@ public void TransactionContextShouldBeSerializedOnlyWhenSampled() nonSampledTransaction.Context.Request = sampledTransaction.Context.Request; var serializedSampledTransaction = _payloadItemSerializer.Serialize(sampledTransaction); - var deserializedSampledTransaction = JsonConvert.DeserializeObject(serializedSampledTransaction); + var deserializedSampledTransaction = _payloadItemSerializer.Deserialize(serializedSampledTransaction); var serializedNonSampledTransaction = _payloadItemSerializer.Serialize(nonSampledTransaction); - var deserializedNonSampledTransaction = JsonConvert.DeserializeObject(serializedNonSampledTransaction); + var deserializedNonSampledTransaction = _payloadItemSerializer.Deserialize(serializedNonSampledTransaction); // ReSharper disable once PossibleNullReferenceException - deserializedSampledTransaction["sampled"].Value().Should().BeTrue(); + deserializedSampledTransaction["sampled"].GetValue().Should().BeTrue(); deserializedSampledTransaction["context"]["request"]["url"]["full"] - .Value() + .GetValue() .Should() .Be("https://elastic.co"); // ReSharper disable once PossibleNullReferenceException - deserializedNonSampledTransaction["sampled"].Value().Should().BeFalse(); + deserializedNonSampledTransaction["sampled"].GetValue().Should().BeFalse(); deserializedNonSampledTransaction.Should().NotContainKey("context"); } @@ -333,34 +335,34 @@ public void SerializationUtilsTruncateToPropertyMaxLengthTests(string original, public void LabelDeDotting() { var context = new Context(); - context.InternalLabels.Value.InnerDictionary["a.b"] = "labelValue"; + context.InternalLabels.InnerDictionary["a.b"] = "labelValue"; var json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b\":\"labelValue\"}}"); context = new Context(); - context.InternalLabels.Value.InnerDictionary["a.b.c"] = "labelValue"; + context.InternalLabels.InnerDictionary["a.b.c"] = "labelValue"; json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b_c\":\"labelValue\"}}"); context = new Context(); - context.InternalLabels.Value.InnerDictionary["a.b"] = "labelValue1"; - context.InternalLabels.Value.InnerDictionary["a.b.c"] = "labelValue2"; + context.InternalLabels.InnerDictionary["a.b"] = "labelValue1"; + context.InternalLabels.InnerDictionary["a.b.c"] = "labelValue2"; json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b\":\"labelValue1\",\"a_b_c\":\"labelValue2\"}}"); context = new Context(); - context.InternalLabels.Value.InnerDictionary["a\"b"] = "labelValue"; + context.InternalLabels.InnerDictionary["a\"b"] = "labelValue"; json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b\":\"labelValue\"}}"); context = new Context(); - context.InternalLabels.Value.InnerDictionary["a*b"] = "labelValue"; + context.InternalLabels.InnerDictionary["a*b"] = "labelValue"; json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b\":\"labelValue\"}}"); context = new Context(); - context.InternalLabels.Value.InnerDictionary["a*b"] = "labelValue1"; - context.InternalLabels.Value.InnerDictionary["a\"b_c"] = "labelValue2"; + context.InternalLabels.InnerDictionary["a*b"] = "labelValue1"; + context.InternalLabels.InnerDictionary["a\"b_c"] = "labelValue2"; json = _payloadItemSerializer.Serialize(context); json.Should().Be("{\"tags\":{\"a_b\":\"labelValue1\",\"a_b_c\":\"labelValue2\"}}"); } @@ -409,13 +411,13 @@ public void MetricSet_Serializes_And_Deserializes() { var samples = new List { - new MetricSample("sample_1", 1), new MetricSample("sample*\"2", 2), new MetricSample("sample_1", 3) + new MetricSample("sample_1", 1), new MetricSample("sample*\"2", 2.1), new MetricSample("sample_1", 3) }; var metricSet = new Elastic.Apm.Metrics.MetricSet(1603343944891, samples); var json = _payloadItemSerializer.Serialize(metricSet); - json.Should().Be("{\"samples\":{\"sample_1\":{\"value\":1.0},\"sample__2\":{\"value\":2.0}},\"timestamp\":1603343944891}"); + json.Should().Be("{\"samples\":{\"sample_1\":{\"value\":1},\"sample__2\":{\"value\":2.1}},\"timestamp\":1603343944891}"); var deserialized = _payloadItemSerializer.Deserialize(json); deserialized.Timestamp.Should().Be(metricSet.Timestamp); @@ -504,10 +506,10 @@ public void DroppedSpanStatsTest() private class DummyType { // ReSharper disable once CollectionNeverQueried.Local - it's by JsonConvert - public Dictionary DictionaryProp { get; } = new Dictionary(); - public int IntProp { get; set; } + public Dictionary Dict { get; } = new(); + public int Int { get; set; } - public string StringProp { get; set; } + public string Str { get; set; } } } } diff --git a/test/Elastic.Apm.Tests/ServiceResourceTests.cs b/test/Elastic.Apm.Tests/ServiceResourceTests.cs index dc5570b20..76277ed1a 100644 --- a/test/Elastic.Apm.Tests/ServiceResourceTests.cs +++ b/test/Elastic.Apm.Tests/ServiceResourceTests.cs @@ -4,8 +4,9 @@ // See the LICENSE file in the project root for more information using System; +using System.Text.Json.Serialization; using Elastic.Apm.Api; -using Elastic.Apm.Libraries.Newtonsoft.Json; +using Elastic.Apm.Report.Serialization; using Elastic.Apm.Tests.Utilities; using FluentAssertions; using TestData; @@ -92,13 +93,17 @@ namespace TestData { public class Input { + [JsonPropertyName("span")] public Span Span { get; set; } - [JsonProperty("expected_resource")] public string ExpectedResource { get; set; } - [JsonProperty("expected_service_target")] + [JsonPropertyName("expected_resource")] + public string ExpectedResource { get; set; } + + [JsonPropertyName("expected_service_target")] public ExpectedServiceTarget ExpectedServiceTarget { get; set; } - [JsonProperty("failure_message")] public string FailureMessage { get; set; } + [JsonPropertyName("failure_message")] + public string FailureMessage { get; set; } } public class Context @@ -144,8 +149,10 @@ public class Service public class Span { + [JsonConverter(typeof(BooleanConverter))] public bool Exit { get; set; } public string Type { get; set; } + [JsonPropertyName("subtype")] public string SubType { get; set; } public Context Context { get; set; } } diff --git a/test/Elastic.Apm.Tests/TestHelpers/TestingConfigTests.cs b/test/Elastic.Apm.Tests/TestHelpers/TestingConfigTests.cs index da61d7f22..49497bd48 100644 --- a/test/Elastic.Apm.Tests/TestHelpers/TestingConfigTests.cs +++ b/test/Elastic.Apm.Tests/TestHelpers/TestingConfigTests.cs @@ -155,7 +155,7 @@ public void Option_without_value_should_be_set_to_default() var allDefaultsConfigSnapshot = new MutableSnapshot(new MockRawConfigSnapshot(new Dictionary()), _xunitOutputHelper); Options.All.ForEach(optMeta => { - optMeta.MutableSnapshotPropertyInfo.GetValue(allDefaultsConfigSnapshot).Should().Be(optMeta.DefaultValueAsObject); + optMeta.MutableSnapshotPropertyInfo.GetValue(allDefaultsConfigSnapshot).Should().Be(optMeta.DefaultValueAsObject, $"{optMeta.Name}"); }); } diff --git a/test/Elastic.Apm.Tests/WildcardMatcherTests.cs b/test/Elastic.Apm.Tests/WildcardMatcherTests.cs index ac097e578..22f6f548b 100644 --- a/test/Elastic.Apm.Tests/WildcardMatcherTests.cs +++ b/test/Elastic.Apm.Tests/WildcardMatcherTests.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Text.Json.Nodes; using Elastic.Apm.Helpers; -using Elastic.Apm.Libraries.Newtonsoft.Json.Linq; using Elastic.Apm.Tests.Utilities; using FluentAssertions; using Xunit; @@ -22,14 +22,15 @@ public class WildcardMatcherTests [JsonFileData("./TestResources/json-specs/wildcard_matcher_tests.json")] public void TestCasesFromJsonSpec(string testCaseName, dynamic data) { - var testData = (JObject)data; - var key = testData.Properties().First(); - var value = (JObject)key.Last; - var matcher = WildcardMatcher.ValueOf(key.Name); + var testData = (JsonObject)data; + var prop = testData.ToArray().First(); + var key = prop.Key; + var value = (JsonObject)prop.Value; + var matcher = WildcardMatcher.ValueOf(key); foreach (var kvp in value) { var input = kvp.Key; - var expected = kvp.Value.Value(); + var expected = kvp.Value.GetValue(); matcher.Matches(input).Should().Be(expected); } } diff --git a/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/DocumentItem.cs b/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/DocumentItem.cs index 4abb353e1..4b95aa1f9 100644 --- a/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/DocumentItem.cs +++ b/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/DocumentItem.cs @@ -3,13 +3,13 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Elastic.Apm.Azure.CosmosDb.Tests { public class DocumentItem { - [JsonProperty("id")] + [JsonPropertyName("id")] public string Id { get; set; } public string FirstName { get; set; } diff --git a/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/Elastic.Apm.Azure.CosmosDb.Tests.csproj b/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/Elastic.Apm.Azure.CosmosDb.Tests.csproj index 3e149fc8c..935be6a47 100644 --- a/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/Elastic.Apm.Azure.CosmosDb.Tests.csproj +++ b/test/azure/Elastic.Apm.Azure.CosmosDb.Tests/Elastic.Apm.Azure.CosmosDb.Tests.csproj @@ -13,7 +13,6 @@ - diff --git a/test/azure/Elastic.Apm.Azure.ServiceBus.Tests/Elastic.Apm.Azure.ServiceBus.Tests.csproj b/test/azure/Elastic.Apm.Azure.ServiceBus.Tests/Elastic.Apm.Azure.ServiceBus.Tests.csproj index 91993cdee..38bdcbb13 100644 --- a/test/azure/Elastic.Apm.Azure.ServiceBus.Tests/Elastic.Apm.Azure.ServiceBus.Tests.csproj +++ b/test/azure/Elastic.Apm.Azure.ServiceBus.Tests/Elastic.Apm.Azure.ServiceBus.Tests.csproj @@ -10,7 +10,6 @@ - diff --git a/test/azure/Elastic.Apm.Azure.Storage.Tests/Elastic.Apm.Azure.Storage.Tests.csproj b/test/azure/Elastic.Apm.Azure.Storage.Tests/Elastic.Apm.Azure.Storage.Tests.csproj index b9c002692..eba95dc6e 100644 --- a/test/azure/Elastic.Apm.Azure.Storage.Tests/Elastic.Apm.Azure.Storage.Tests.csproj +++ b/test/azure/Elastic.Apm.Azure.Storage.Tests/Elastic.Apm.Azure.Storage.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/test/integrations/Elastic.Apm.AspNetCore.Tests/AspNetCoreBasicTests.cs b/test/integrations/Elastic.Apm.AspNetCore.Tests/AspNetCoreBasicTests.cs index 137eeb935..a4c87e661 100644 --- a/test/integrations/Elastic.Apm.AspNetCore.Tests/AspNetCoreBasicTests.cs +++ b/test/integrations/Elastic.Apm.AspNetCore.Tests/AspNetCoreBasicTests.cs @@ -409,7 +409,7 @@ public async Task FailingRequestWithoutConfiguredExceptionPage() var errorDetail = error?.Exception; errorDetail.Should().NotBeNull(); - var labels = error?.Context.InternalLabels.Value.InnerDictionary; + var labels = error?.Context.InternalLabels.InnerDictionary; labels.Should().NotBeEmpty().And.ContainKey("foo"); var val = labels?["foo"]; val.Should().NotBeNull(); diff --git a/test/integrations/applications/SampleAspNetCoreApp/Controllers/HomeController.cs b/test/integrations/applications/SampleAspNetCoreApp/Controllers/HomeController.cs index 8b19dbf04..040a701ef 100644 --- a/test/integrations/applications/SampleAspNetCoreApp/Controllers/HomeController.cs +++ b/test/integrations/applications/SampleAspNetCoreApp/Controllers/HomeController.cs @@ -10,6 +10,8 @@ using System.Net.Http; using System.Runtime.CompilerServices; using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Elastic.Apm; @@ -18,9 +20,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OpenTelemetry; using SampleAspNetCoreApp.Data; using SampleAspNetCoreApp.Models; using SampleAspNetCoreApp.Utils; @@ -66,7 +65,7 @@ public Task Index() => httpClient.DefaultRequestHeaders.Add("User-Agent", "APM-Sample-App"); var responseMsg = await httpClient.GetAsync("https://api.github.com/repos/elastic/apm-agent-dotnet"); var responseStr = await responseMsg.Content.ReadAsStringAsync(); - ViewData["stargazers_count"] = JObject.Parse(responseStr)["stargazers_count"]; + ViewData["stargazers_count"] = JsonNode.Parse(responseStr)!["stargazers_count"]; } catch { @@ -137,7 +136,7 @@ public async Task DistributedTracingMiniSample() var retVal = await httpClient.GetAsync("http://localhost:5050/api/values"); var resultInStr = await retVal.Content.ReadAsStringAsync(); - var list = JsonConvert.DeserializeObject>(resultInStr); + var list = JsonSerializer.Deserialize>(resultInStr); return View(list); } catch (Exception e) diff --git a/test/integrations/applications/SampleAspNetCoreApp/SampleAspNetCoreApp.csproj b/test/integrations/applications/SampleAspNetCoreApp/SampleAspNetCoreApp.csproj index 758744247..7e05243ec 100644 --- a/test/integrations/applications/SampleAspNetCoreApp/SampleAspNetCoreApp.csproj +++ b/test/integrations/applications/SampleAspNetCoreApp/SampleAspNetCoreApp.csproj @@ -5,9 +5,6 @@ false AnyCPU - - - diff --git a/test/profiler/applications/KafkaSample/Consumer.cs b/test/profiler/applications/KafkaSample/Consumer.cs index 5f0a955f6..3205bf4ab 100644 --- a/test/profiler/applications/KafkaSample/Consumer.cs +++ b/test/profiler/applications/KafkaSample/Consumer.cs @@ -8,12 +8,12 @@ using System; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Confluent.Kafka; using Elastic.Apm; using Elastic.Apm.Api; -using Newtonsoft.Json; namespace KafkaSample { @@ -174,7 +174,7 @@ private void HandleMessage(ConsumeResult consumeResult) } else { - var sampleMessage = JsonConvert.DeserializeObject(kafkaMessage.Value); + var sampleMessage = JsonSerializer.Deserialize(kafkaMessage.Value); Console.WriteLine($"Received {(sampleMessage.IsProducedAsync ? "async" : "sync")}message for {kafkaMessage.Key}"); if (sampleMessage.IsProducedAsync) Interlocked.Increment(ref TotalAsyncMessages); diff --git a/test/profiler/applications/KafkaSample/KafkaSample.csproj b/test/profiler/applications/KafkaSample/KafkaSample.csproj index 3f2b25136..151fe782f 100644 --- a/test/profiler/applications/KafkaSample/KafkaSample.csproj +++ b/test/profiler/applications/KafkaSample/KafkaSample.csproj @@ -8,7 +8,6 @@ - diff --git a/test/profiler/applications/KafkaSample/Producer.cs b/test/profiler/applications/KafkaSample/Producer.cs index fbd37754c..ae7026f03 100644 --- a/test/profiler/applications/KafkaSample/Producer.cs +++ b/test/profiler/applications/KafkaSample/Producer.cs @@ -7,13 +7,14 @@ // Licensed under Apache 2.0 using System; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Confluent.Kafka; using Elastic.Apm; using Elastic.Apm.Api; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace KafkaSample { @@ -97,7 +98,8 @@ private static void HandleDelivery(DeliveryReport deliveryReport private static string GetMessage(int iteration, bool isProducedAsync) { var message = new SampleMessage("fruit", iteration, isProducedAsync); - return JObject.FromObject(message).ToString(Formatting.None); + var json = JsonSerializer.SerializeToUtf8Bytes(message, new JsonSerializerOptions { WriteIndented = false}); + return Encoding.UTF8.GetString(json); } } } From 073ed443b047f6ceb25ca734876ea7258644090b Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 23 Oct 2024 20:02:51 +0200 Subject: [PATCH 02/17] update formatting --- src/Elastic.Apm/Model/LabelsDictionary.cs | 2 +- src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs | 2 +- src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs | 2 +- test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs | 2 +- test/profiler/applications/KafkaSample/Producer.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Elastic.Apm/Model/LabelsDictionary.cs b/src/Elastic.Apm/Model/LabelsDictionary.cs index b8306f9b3..8eeed7e5e 100644 --- a/src/Elastic.Apm/Model/LabelsDictionary.cs +++ b/src/Elastic.Apm/Model/LabelsDictionary.cs @@ -44,7 +44,7 @@ internal Dictionary ExposeDictionary() => .Replace('.', '_') .Replace('*', '_') .Replace('"', '_'), - v=>v.Value.ToString() + v => v.Value.ToString() ); } } diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index 17c892b59..a8e64f460 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -114,7 +114,7 @@ internal T Deserialize(Stream stream) /// internal string Serialize(object item) { - var bytes= JsonSerializer.SerializeToUtf8Bytes(item, item.GetType(), Settings); + var bytes = JsonSerializer.SerializeToUtf8Bytes(item, item.GetType(), Settings); return Encoding.UTF8.GetString(bytes); } } diff --git a/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs b/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs index d39e55558..6465091d1 100644 --- a/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/TruncateJsonConverter.cs @@ -26,7 +26,7 @@ public TruncateJsonConverter() : this(Consts.PropertyMaxLength) { } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => writer.WriteStringValue(value.Truncate(MaxLength)); - public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => reader.GetString(); diff --git a/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs b/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs index 1a242c411..0cb23398f 100644 --- a/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs +++ b/test/Elastic.Apm.Tests.Utilities/CGroupTestCasesAttribute.cs @@ -72,7 +72,7 @@ private static CGroupTestData ParseTestData(JsonObject jToken) var cgroupA = o.TryGetPropertyValue("/proc/self/cgroup", out var cgroup) ? cgroup as JsonArray : null; testData.Files.ProcSelfCgroup = cgroupA?.GetValues().FirstOrDefault(); - var mountInfoA = o.TryGetPropertyValue("/proc/self/mountinfo", out var mountinfo) ? mountinfo as JsonArray : null; + var mountInfoA = o.TryGetPropertyValue("/proc/self/mountinfo", out var mountinfo) ? mountinfo as JsonArray : null; testData.Files.MountInfo = mountInfoA?.GetValues().ToArray(); break; } diff --git a/test/profiler/applications/KafkaSample/Producer.cs b/test/profiler/applications/KafkaSample/Producer.cs index ae7026f03..a202f3ca3 100644 --- a/test/profiler/applications/KafkaSample/Producer.cs +++ b/test/profiler/applications/KafkaSample/Producer.cs @@ -98,7 +98,7 @@ private static void HandleDelivery(DeliveryReport deliveryReport private static string GetMessage(int iteration, bool isProducedAsync) { var message = new SampleMessage("fruit", iteration, isProducedAsync); - var json = JsonSerializer.SerializeToUtf8Bytes(message, new JsonSerializerOptions { WriteIndented = false}); + var json = JsonSerializer.SerializeToUtf8Bytes(message, new JsonSerializerOptions { WriteIndented = false }); return Encoding.UTF8.GetString(json); } } From 513e345cec542764137179daf41903d00433d0f5 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Fri, 29 Nov 2024 11:20:13 +0000 Subject: [PATCH 03/17] Update formatting --- .../Report/Serialization/PayloadItemSerializer.cs | 3 +-- .../Controllers/IntakeV2EventsController.cs | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index a8e64f460..e6e64d76e 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -45,8 +45,7 @@ internal PayloadItemSerializer() => { foreach (var prop in j.Properties) { - var maxLengthAttribute = prop.AttributeProvider.GetCustomAttributes(typeof(MaxLengthAttribute), false).FirstOrDefault() as MaxLengthAttribute; - if (maxLengthAttribute != null) + if (prop.AttributeProvider.GetCustomAttributes(typeof(MaxLengthAttribute), false).FirstOrDefault() is MaxLengthAttribute maxLengthAttribute) prop.CustomConverter = new TruncateJsonConverter(maxLengthAttribute.Length); if (prop.PropertyType == typeof(Lazy)) diff --git a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs index 8c3dc66b9..2e78c2445 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs @@ -105,10 +105,7 @@ private async Task ParsePayloadLineAndAddToReceivedData(string line) new JsonSerializerOptions { UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, - }); - - if (payload is null) - throw new ArgumentException("Deserialization failed"); + }) ?? throw new ArgumentException("Deserialization failed"); await HandleParsed(nameof(payload.Error), payload.Error, _mockApmServer.ReceivedData.Errors, _mockApmServer.AddError); await HandleParsed(nameof(payload.Metadata), payload.Metadata, _mockApmServer.ReceivedData.Metadata, _mockApmServer.AddMetadata); From 2d8eeb8870d7a183c19e210a176e34d81c4d4d76 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Fri, 29 Nov 2024 13:59:42 +0000 Subject: [PATCH 04/17] Fix tracer --- src/Elastic.Apm/Api/Tracer.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Elastic.Apm/Api/Tracer.cs b/src/Elastic.Apm/Api/Tracer.cs index cb0110d5c..dce255cc9 100644 --- a/src/Elastic.Apm/Api/Tracer.cs +++ b/src/Elastic.Apm/Api/Tracer.cs @@ -78,13 +78,12 @@ private Transaction StartTransactionInternal(string name, string type, Distribut ) { var currentConfig = _configurationProvider.CurrentSnapshot; - var retVal = new Transaction(_logger, name, type, new Sampler(currentConfig.TransactionSampleRate), distributedTracingData - , _sender, currentConfig, CurrentExecutionSegmentsContainer, _apmServerInfo, _breakdownMetricsProvider, ignoreActivity, timestamp, id, + var transaction = new Transaction(_logger, name, type, new Sampler(currentConfig.TransactionSampleRate), distributedTracingData, + _sender, currentConfig, CurrentExecutionSegmentsContainer, _apmServerInfo, _breakdownMetricsProvider, ignoreActivity, timestamp, id, traceId: traceId, links: links, current: current); - retVal.Context.Service = _service; - _logger?.Debug()?.Log("Starting {TransactionValue}", retVal); - return retVal; + _logger?.Debug()?.Log("Starting {TransactionValue}", transaction); + return transaction; } public void CaptureTransaction(string name, string type, Action action, DistributedTracingData distributedTracingData = null, IEnumerable links = null) From ce8297ef846138fd4b81e036e98ee3601cd983cd Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Fri, 29 Nov 2024 15:59:28 +0000 Subject: [PATCH 05/17] update tests --- src/Elastic.Apm/Api/Tracer.cs | 10 ++++++---- .../HelpersTests/PlatformDetectionTests.cs | 13 ++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Elastic.Apm/Api/Tracer.cs b/src/Elastic.Apm/Api/Tracer.cs index dce255cc9..416e1c803 100644 --- a/src/Elastic.Apm/Api/Tracer.cs +++ b/src/Elastic.Apm/Api/Tracer.cs @@ -23,7 +23,7 @@ internal class Tracer : ITracer private readonly IConfigurationSnapshotProvider _configurationProvider; private readonly IApmLogger _logger; private readonly IPayloadSender _sender; - private readonly Service _service; + private readonly BreakdownMetricsProvider _breakdownMetricsProvider; public Tracer( @@ -37,13 +37,14 @@ BreakdownMetricsProvider breakdownMetricsProvider ) { _logger = logger?.Scoped(nameof(Tracer)); - _service = service; _sender = payloadSender.ThrowIfArgumentNull(nameof(payloadSender)); _configurationProvider = configurationProvider.ThrowIfArgumentNull(nameof(configurationProvider)); - CurrentExecutionSegmentsContainer = currentExecutionSegmentsContainer.ThrowIfArgumentNull(nameof(currentExecutionSegmentsContainer)); - DbSpanCommon = new DbSpanCommon(logger); _apmServerInfo = apmServerInfo; _breakdownMetricsProvider = breakdownMetricsProvider; + + CurrentExecutionSegmentsContainer = currentExecutionSegmentsContainer.ThrowIfArgumentNull(nameof(currentExecutionSegmentsContainer)); + DbSpanCommon = new DbSpanCommon(logger); + Service = service; } internal ICurrentExecutionSegmentsContainer CurrentExecutionSegmentsContainer { get; } @@ -53,6 +54,7 @@ BreakdownMetricsProvider breakdownMetricsProvider public ITransaction CurrentTransaction => CurrentExecutionSegmentsContainer.CurrentTransaction; public DbSpanCommon DbSpanCommon { get; } + internal Service Service { get; } public ITransaction StartTransaction(string name, string type, DistributedTracingData distributedTracingData = null, bool ignoreActivity = false, IEnumerable links = null diff --git a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs index b8c7f8e33..274a986fa 100644 --- a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs +++ b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs @@ -19,24 +19,23 @@ public class PlatformDetectionTests [Fact] public void RuntimeName() { - var mockPayloadSender = new MockPayloadSender(); - using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: mockPayloadSender))) - agent.Tracer.CaptureTransaction("TestTransaction", "Test", () => { }); + var mockPayloadSender = new NoopPayloadSender(); + using var agent = new ApmAgent(new TestAgentComponents(payloadSender: mockPayloadSender)); switch (RuntimeInformation.FrameworkDescription) { case { } str when str.StartsWith(Runtime.MonoName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.MonoName); + agent.Service.Runtime.Name.Should().Be(Runtime.MonoName); break; case { } str when str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); break; case { } str when str.StartsWith(Runtime.DotNetCoreName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); break; case { } str when str.StartsWith(Runtime.DotNetName, StringComparison.OrdinalIgnoreCase) && !str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - mockPayloadSender.FirstTransaction.Context.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); break; } } From 478964345d40ddb17d6a6fa8f5e651446e63c7a8 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Fri, 29 Nov 2024 16:09:05 +0000 Subject: [PATCH 06/17] Fix formatting --- .../HelpersTests/PlatformDetectionTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs index 274a986fa..804efd0b5 100644 --- a/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs +++ b/test/Elastic.Apm.Tests/HelpersTests/PlatformDetectionTests.cs @@ -25,17 +25,17 @@ public void RuntimeName() switch (RuntimeInformation.FrameworkDescription) { case { } str when str.StartsWith(Runtime.MonoName, StringComparison.OrdinalIgnoreCase): - agent.Service.Runtime.Name.Should().Be(Runtime.MonoName); + agent.Service.Runtime.Name.Should().Be(Runtime.MonoName); break; case { } str when str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - agent.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetFullFrameworkName); break; case { } str when str.StartsWith(Runtime.DotNetCoreName, StringComparison.OrdinalIgnoreCase): - agent.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); break; case { } str when str.StartsWith(Runtime.DotNetName, StringComparison.OrdinalIgnoreCase) && !str.StartsWith(Runtime.DotNetFullFrameworkName, StringComparison.OrdinalIgnoreCase): - agent.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); + agent.Service.Runtime.Name.Should().Be(Runtime.DotNetName + $" {RuntimeInformation.FrameworkDescription.Substring(5).Split('.')[0]}"); break; } } From 7b9291ba1e5d1cafc96f6c7b8983f40bfc275d32 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 2 Dec 2024 09:26:09 +0000 Subject: [PATCH 07/17] Fixing failing tests --- Directory.Packages.props | 2 +- .../Elastic.Apm.Specification.csproj | 1 - src/Elastic.Apm/Api/Service.cs | 1 + .../Serialization/PayloadItemSerializer.cs | 2 +- .../ContextDto.cs | 3 ++- .../Controllers/IntakeV2EventsController.cs | 26 +++++++++++-------- test/Elastic.Apm.Tests/SerializationTests.cs | 2 +- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a9ec50b0f..2029d4bf1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -44,7 +44,7 @@ - + diff --git a/src/Elastic.Apm.Specification/Elastic.Apm.Specification.csproj b/src/Elastic.Apm.Specification/Elastic.Apm.Specification.csproj index 43d6863ef..2cdfedea2 100644 --- a/src/Elastic.Apm.Specification/Elastic.Apm.Specification.csproj +++ b/src/Elastic.Apm.Specification/Elastic.Apm.Specification.csproj @@ -8,7 +8,6 @@ - diff --git a/src/Elastic.Apm/Api/Service.cs b/src/Elastic.Apm/Api/Service.cs index 6adde8191..5fee34e66 100644 --- a/src/Elastic.Apm/Api/Service.cs +++ b/src/Elastic.Apm/Api/Service.cs @@ -17,6 +17,7 @@ public class Service { private Service() { } + [JsonConstructor] internal Service(string name, string version) => (Name, Version) = (name, version); public AgentC Agent { get; set; } diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index e6e64d76e..42a04dfc0 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -38,7 +38,7 @@ internal PayloadItemSerializer() => PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, WriteIndented = false, - Converters = { new JsonConverterDouble(), new JsonConverterDecimal() }, + Converters = { new JsonConverterDouble(), new JsonConverterDecimal(), new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower) }, TypeInfoResolver = JsonTypeInfoResolver.Combine(SourceGenerationContext.Default, new DefaultJsonTypeInfoResolver { Modifiers = { j => diff --git a/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs b/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs index f281e6499..deacb6160 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/ContextDto.cs @@ -5,8 +5,8 @@ using System.Text.Json.Serialization; using Elastic.Apm.Api; using Elastic.Apm.Helpers; - using Elastic.Apm.Model; +using Elastic.Apm.Report.Serialization; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global @@ -16,6 +16,7 @@ namespace Elastic.Apm.Tests.MockApmServer internal class ContextDto : IDto { [JsonPropertyName("tags")] + [JsonConverter(typeof(LabelsJsonConverter))] public LabelsDictionary Labels { get; set; } public Request Request { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs index 2e78c2445..5f93d950b 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs @@ -18,7 +18,9 @@ using Elastic.Apm.Specification; using Elastic.Apm.Tests.Utilities; using FluentAssertions; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; +using Namotion.Reflection; using NJsonSchema; using Xunit.Sdk; using JsonSerializerOptions = System.Text.Json.JsonSerializerOptions; @@ -31,8 +33,13 @@ namespace Elastic.Apm.Tests.MockApmServer.Controllers [ApiController] public class IntakeV2EventsController : ControllerBase { - private static readonly ConcurrentDictionary>> Schemata = - new ConcurrentDictionary>>(); + private static readonly ConcurrentDictionary>> Schemata = new(); + + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; private const string ExpectedContentType = "application/x-ndjson; charset=utf-8"; private const string ThisClassName = nameof(IntakeV2EventsController); @@ -100,12 +107,8 @@ private async Task ParsePayload() private async Task ParsePayloadLineAndAddToReceivedData(string line) { var foundDto = false; - var payload = JsonSerializer.Deserialize( - line, - new JsonSerializerOptions - { - UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, - }) ?? throw new ArgumentException("Deserialization failed"); + var payload = JsonSerializer + .Deserialize(line, JsonSerializerOptions) ?? throw new ArgumentException("Deserialization failed"); await HandleParsed(nameof(payload.Error), payload.Error, _mockApmServer.ReceivedData.Errors, _mockApmServer.AddError); await HandleParsed(nameof(payload.Metadata), payload.Metadata, _mockApmServer.ReceivedData.Metadata, _mockApmServer.AddMetadata); @@ -136,11 +139,12 @@ async Task HandleParsed(string dtoType, TDto dto, ImmutableList accu }, _validator) .Value; - var jObject = JsonNode.Parse(line) as JsonObject; - var value = jObject!.TryGetPropertyValue(dtoType, out var dtoValue) ? dtoValue.GetValue() : null; + using var jsonDocument = JsonDocument.Parse(line); - var validationErrors = schema.Validate(value); + var root = jsonDocument.RootElement; + var property = root.GetProperty(dtoType.ToLower()); + var validationErrors = schema.Validate(property.ToString()); validationErrors.Should().BeEmpty(); } catch (Exception ex) diff --git a/test/Elastic.Apm.Tests/SerializationTests.cs b/test/Elastic.Apm.Tests/SerializationTests.cs index 77e4a0973..304f59c7b 100644 --- a/test/Elastic.Apm.Tests/SerializationTests.cs +++ b/test/Elastic.Apm.Tests/SerializationTests.cs @@ -411,7 +411,7 @@ public void MetricSet_Serializes_And_Deserializes() { var samples = new List { - new MetricSample("sample_1", 1), new MetricSample("sample*\"2", 2.1), new MetricSample("sample_1", 3) + new("sample_1", 1), new("sample*\"2", 2.1), new("sample_1", 3) }; var metricSet = new Elastic.Apm.Metrics.MetricSet(1603343944891, samples); From 77cb64d49b9487df30addba2135b3bb19e00747f Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 2 Dec 2024 11:22:38 +0000 Subject: [PATCH 08/17] Fix MetricSetConverter for net462 --- .../Report/Serialization/MetricSetConverter.cs | 2 +- .../Report/Serialization/PayloadItemSerializer.cs | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs index b04fa87b5..e5c5e3e0e 100644 --- a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs @@ -63,7 +63,7 @@ public override void Write(Utf8JsonWriter writer, MetricSet value, JsonSerialize .Replace('"', '_')); writer.WriteStartObject(); writer.WritePropertyName("value"); - writer.WriteNumberValue(item.KeyValue.Value); + writer.WriteNumberValue((decimal)item.KeyValue.Value); writer.WriteEndObject(); } } diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index 42a04dfc0..ad38182dd 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -4,8 +4,6 @@ using System; using System.Collections; -using System.ComponentModel; -using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -111,9 +109,5 @@ internal T Deserialize(Stream stream) /// /// /// - internal string Serialize(object item) - { - var bytes = JsonSerializer.SerializeToUtf8Bytes(item, item.GetType(), Settings); - return Encoding.UTF8.GetString(bytes); - } + internal string Serialize(object item) => JsonSerializer.Serialize(item, item.GetType(), Settings); } From e8c3aaeec6cba839d8fcd360a28ab4cad1ce2317 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 2 Dec 2024 14:42:48 +0000 Subject: [PATCH 09/17] Fix serialization --- .../Serialization/PayloadItemSerializer.cs | 5 ++- .../ActivityIntegrationTests.cs | 12 +++--- .../StartupHookTests.cs | 41 ++++++++++++++++--- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs index ad38182dd..a3023e328 100644 --- a/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs +++ b/src/Elastic.Apm/Report/Serialization/PayloadItemSerializer.cs @@ -83,8 +83,11 @@ internal PayloadItemSerializer() => public JsonTypeInfo GetTypeInfo(Type type) => Settings.TypeInfoResolver!.GetTypeInfo(type, Settings); - public void Serialize(object item, StreamWriter writer) => + public void Serialize(object item, StreamWriter writer) + { + writer.Flush(); // ensure the base stream is "up-to-date" before we attempt to serialize into it JsonSerializer.Serialize(writer.BaseStream, item, item.GetType(), Settings); + } /// /// Deserializes an instance of from JSON diff --git a/test/Elastic.Apm.Tests/ActivityIntegrationTests.cs b/test/Elastic.Apm.Tests/ActivityIntegrationTests.cs index fe232020e..a9de5c6ef 100644 --- a/test/Elastic.Apm.Tests/ActivityIntegrationTests.cs +++ b/test/Elastic.Apm.Tests/ActivityIntegrationTests.cs @@ -168,9 +168,6 @@ public void MultipleTransactionInOneActivity() } #if NET - /// - /// Makes sure that transactions on the same Activity are part of the same trace. - /// [Fact] public async Task ActivityRespectsSampling() { @@ -179,19 +176,20 @@ public async Task ActivityRespectsSampling() Activity.Current = null; Activity.DefaultIdFormat = ActivityIdFormat.W3C; - var source = new ActivitySource(GetType().FullName, "1.0.0"); + + using var source = new ActivitySource(GetType().FullName, "1.0.0"); var payloadSender = new MockPayloadSender(); var config = new MockConfiguration( transactionSampleRate: rate.ToString("N2") - ); + using var components = new TestAgentComponents( apmServerInfo: MockApmServerInfo.Version716, configuration: config, payloadSender: payloadSender - ); + using var agent = new ApmAgent(components); for (var i = 0; i < count; i++) { @@ -199,7 +197,7 @@ public async Task ActivityRespectsSampling() using var span = new Activity("UnitTestActivity").Start(); await Task.Delay(1); } - //Activity.Current.Should().BeNull(); + payloadSender.WaitForTransactions(count: count); var sampled = payloadSender.Transactions.Where(t => t.IsSampled).ToArray(); diff --git a/test/startuphook/Elastic.Apm.StartupHook.Tests/StartupHookTests.cs b/test/startuphook/Elastic.Apm.StartupHook.Tests/StartupHookTests.cs index 8810d7bee..af25e06eb 100644 --- a/test/startuphook/Elastic.Apm.StartupHook.Tests/StartupHookTests.cs +++ b/test/startuphook/Elastic.Apm.StartupHook.Tests/StartupHookTests.cs @@ -67,10 +67,18 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Transaction(st apmServer.RunInBackground(port); var waitHandle = new ManualResetEvent(false); + var error = string.Empty; + apmServer.OnReceive += o => { if (o is TransactionDto) waitHandle.Set(); + + else if (o is string s) // may occur if there is an error + { + waitHandle.Set(); + error = s; + } }; using (var sampleApp = new SampleApplication()) @@ -86,8 +94,9 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Transaction(st var response = await client.GetAsync(uri); response.IsSuccessStatusCode.Should().BeTrue(); + waitHandle.WaitOne(TimeSpan.FromMinutes(1)); - waitHandle.WaitOne(TimeSpan.FromMinutes(2)); + error.Should().BeEmpty(); apmServer.ReceivedData.Transactions.Should().HaveCount(1); var transaction = apmServer.ReceivedData.Transactions.First(); @@ -108,12 +117,22 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Error(string t var transactionWaitHandle = new ManualResetEvent(false); var errorWaitHandle = new ManualResetEvent(false); + var serverError = string.Empty; + apmServer.OnReceive += o => { if (o is TransactionDto) transactionWaitHandle.Set(); - if (o is ErrorDto) + + else if (o is ErrorDto) errorWaitHandle.Set(); + + else if (o is string s) // may occur if there is an error + { + transactionWaitHandle.Set(); + errorWaitHandle.Set(); + serverError = s; + } }; using (var sampleApp = new SampleApplication()) @@ -131,13 +150,15 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Error(string t response.IsSuccessStatusCode.Should().BeFalse(); - transactionWaitHandle.WaitOne(TimeSpan.FromMinutes(2)); + transactionWaitHandle.WaitOne(TimeSpan.FromMinutes(1)); + serverError.Should().BeEmpty(); apmServer.ReceivedData.Transactions.Should().HaveCount(1); var transaction = apmServer.ReceivedData.Transactions.First(); transaction.Name.Should().Be("GET Home/Exception"); - errorWaitHandle.WaitOne(TimeSpan.FromMinutes(2)); + errorWaitHandle.WaitOne(TimeSpan.FromMinutes(1)); + serverError.Should().BeEmpty(); apmServer.ReceivedData.Errors.Should().HaveCount(1); var error = apmServer.ReceivedData.Errors.First(); @@ -159,11 +180,19 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Metadata( var port = apmServer.FindAvailablePortToListen(); apmServer.RunInBackground(port); + var error = string.Empty; var waitHandle = new ManualResetEvent(false); + apmServer.OnReceive += o => { if (o is MetadataDto) waitHandle.Set(); + + else if (o is string s) // may occur if there is an error + { + waitHandle.Set(); + error = s; + } }; using (var sampleApp = new SampleApplication()) @@ -180,7 +209,9 @@ public async Task Auto_Instrument_With_StartupHook_Should_Capture_Metadata( response.IsSuccessStatusCode.Should().BeTrue(); - waitHandle.WaitOne(TimeSpan.FromMinutes(2)); + waitHandle.WaitOne(TimeSpan.FromMinutes(1)); + + error.Should().BeEmpty(); apmServer.ReceivedData.Metadata.Should().HaveCountGreaterOrEqualTo(1); var metadata = apmServer.ReceivedData.Metadata.First(); From 4eee56ebde65d244a7a004c33bca3c8621cc5559 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 3 Dec 2024 11:13:22 +0000 Subject: [PATCH 10/17] Fixes for ASP.NET (Framework) tests --- Directory.Packages.props | 17 +- .../Serialization/MetricSetConverter.cs | 11 +- .../ElasticApmModule.cs | 8 +- .../Areas/MyArea/Web.config | 4 +- .../AspNetFullFrameworkSampleApp.csproj | 10 +- .../Views/Web.config | 4 +- .../AspNetFullFrameworkSampleApp/Web.config | 270 ++++-------------- .../BodyCapturingTests.cs | 84 ++++-- .../TestsBase.cs | 4 +- 9 files changed, 137 insertions(+), 275 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2029d4bf1..922c7cddc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -22,7 +22,7 @@ - + @@ -38,6 +38,9 @@ + + + @@ -63,6 +66,7 @@ + @@ -73,18 +77,19 @@ + - + - - + + - + @@ -119,7 +124,7 @@ - + diff --git a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs index e5c5e3e0e..a922815a8 100644 --- a/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/MetricSetConverter.cs @@ -19,7 +19,6 @@ public override void Write(Utf8JsonWriter writer, MetricSet value, JsonSerialize writer.WriteStartObject(); if (value.Transaction != null) { - writer.WritePropertyName("transaction"); writer.WriteStartObject(); @@ -35,7 +34,6 @@ public override void Write(Utf8JsonWriter writer, MetricSet value, JsonSerialize if (value.Span != null) { - writer.WritePropertyName("span"); writer.WriteStartObject(); @@ -43,13 +41,15 @@ public override void Write(Utf8JsonWriter writer, MetricSet value, JsonSerialize writer.WritePropertyName("type"); writer.WriteStringValue(value.Span.Type); - writer.WritePropertyName("subtype"); - writer.WriteStringValue(value.Span.SubType); + if (value.Span.SubType is not null) + { + writer.WritePropertyName("subtype"); + writer.WriteStringValue(value.Span.SubType); + } writer.WriteEndObject(); } - writer.WritePropertyName("samples"); writer.WriteStartObject(); @@ -128,6 +128,5 @@ public override MetricSet Read(ref Utf8JsonReader reader, Type typeToConvert, Js return new MetricSet(timestamp, samples); } - } } diff --git a/src/integrations/Elastic.Apm.AspNetFullFramework/ElasticApmModule.cs b/src/integrations/Elastic.Apm.AspNetFullFramework/ElasticApmModule.cs index b00e9cf44..50c8732a3 100644 --- a/src/integrations/Elastic.Apm.AspNetFullFramework/ElasticApmModule.cs +++ b/src/integrations/Elastic.Apm.AspNetFullFramework/ElasticApmModule.cs @@ -212,14 +212,14 @@ private void RestoreContextIfNeeded(HttpContextBase context) if (Agent.Instance == null) { _logger.Trace()? - .Log("Agent.Instance is null during {RequestNotification}. url: {{UrlPath}}", + .Log("Agent.Instance is null during {RequestNotification}. url: {UrlPath}", $"{nameof(OnExecuteRequestStep)}:{EventName()}", urlPath); return; } if (Agent.Instance.Tracer == null) { _logger.Trace()? - .Log("Agent.Instance.Tracer is null during {RequestNotification}. url: {{UrlPath}}", + .Log("Agent.Instance.Tracer is null during {RequestNotification}. url: {UrlPath}", $"{nameof(OnExecuteRequestStep)}:{EventName()}", urlPath); return; } @@ -235,10 +235,10 @@ private void RestoreContextIfNeeded(HttpContextBase context) var spanInApplicationInstance = context.Items[HttpContextCurrentExecutionSegmentsContainer.CurrentSpanKey] is not null; _logger.Trace()? - .Log($"{nameof(ITracer.CurrentTransaction)} is null during {{RequestNotification}}. url: {{UrlPath}}" + .Log("{nameof(ITracer.CurrentTransaction)} is null during {RequestNotification}. url: {UrlPath}" + "(HttpContext.Current Span: {HttpContextCurrentHasSpan}, Transaction: {HttpContextCurrenHasTransaction})" + "(ApplicationContext Span: {ApplicationContextHasSpan}, Transaction: {ApplicationContextHasTransaction})", - $"{nameof(OnExecuteRequestStep)}:{EventName()}", urlPath, spanInCurrent, transactionInCurrent, spanInApplicationInstance, transactionInApplicationInstance + nameof(ITracer.CurrentTransaction), $"{nameof(OnExecuteRequestStep)}:{EventName()}", urlPath, spanInCurrent, transactionInCurrent, spanInApplicationInstance, transactionInApplicationInstance ); if (HttpContext.Current == null) diff --git a/test/iis/AspNetFullFrameworkSampleApp/Areas/MyArea/Web.config b/test/iis/AspNetFullFrameworkSampleApp/Areas/MyArea/Web.config index be8136e17..3554f67c2 100644 --- a/test/iis/AspNetFullFrameworkSampleApp/Areas/MyArea/Web.config +++ b/test/iis/AspNetFullFrameworkSampleApp/Areas/MyArea/Web.config @@ -9,7 +9,7 @@ - + @@ -36,7 +36,7 @@ - + diff --git a/test/iis/AspNetFullFrameworkSampleApp/AspNetFullFrameworkSampleApp.csproj b/test/iis/AspNetFullFrameworkSampleApp/AspNetFullFrameworkSampleApp.csproj index fa30e279b..0117753f2 100644 --- a/test/iis/AspNetFullFrameworkSampleApp/AspNetFullFrameworkSampleApp.csproj +++ b/test/iis/AspNetFullFrameworkSampleApp/AspNetFullFrameworkSampleApp.csproj @@ -15,6 +15,7 @@ MSB4011 false false + true @@ -40,8 +41,8 @@ Library AspNetFullFrameworkSampleApp AspNetFullFrameworkSampleApp - v4.6.2 - net462 + v4.8.1 + net481 win @@ -92,11 +93,16 @@ + + + + + diff --git a/test/iis/AspNetFullFrameworkSampleApp/Views/Web.config b/test/iis/AspNetFullFrameworkSampleApp/Views/Web.config index 60d297323..c7005c55f 100644 --- a/test/iis/AspNetFullFrameworkSampleApp/Views/Web.config +++ b/test/iis/AspNetFullFrameworkSampleApp/Views/Web.config @@ -9,7 +9,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/test/iis/AspNetFullFrameworkSampleApp/Web.config b/test/iis/AspNetFullFrameworkSampleApp/Web.config index e44d37826..f6af07b5a 100644 --- a/test/iis/AspNetFullFrameworkSampleApp/Web.config +++ b/test/iis/AspNetFullFrameworkSampleApp/Web.config @@ -1,16 +1,26 @@ - -
+ @@ -23,8 +33,8 @@ - - + + @@ -61,252 +71,68 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + diff --git a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/BodyCapturingTests.cs b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/BodyCapturingTests.cs index 3cf80b85f..7d5ef41f4 100644 --- a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/BodyCapturingTests.cs +++ b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/BodyCapturingTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Elastic.Apm.Helpers; using Elastic.Apm.Tests.Utilities; @@ -44,9 +45,13 @@ private async Task Assert_TextData_RequestBody_IsCaptured(string httpMethod, Sam await SendRequestToSampleAppAndVerifyResponse(new HttpMethod(httpMethod), pathData.Uri, pathData.StatusCode, httpContent: content); await WaitAndCustomVerifyReceivedData(receivedData => { - receivedData.Transactions.Count.Should().Be(1); + receivedData.Transactions.Should().ContainSingle(); var transaction = receivedData.Transactions.Single(); - transaction.Context.Request.Body.Should().Be(textBody); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) + { + element.GetString().Should().Be(textBody); + } }); } @@ -63,11 +68,15 @@ public async Task TextData_RequestBody_IsCaptured_And_Truncated() await SendGetRequestToSampleAppAndVerifyResponse(pathData.Uri, pathData.StatusCode, httpContent: content); await WaitAndCustomVerifyReceivedData(receivedData => { - receivedData.Transactions.Count.Should().Be(1); + receivedData.Transactions.Should().ContainSingle(); var transaction = receivedData.Transactions.Single(); - var body = transaction.Context.Request.Body.ToString(); - body.Should().Contain(textFragment); - body.Length.Should().Be(RequestBodyStreamHelper.RequestBodyMaxLength); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) + { + var body = element.GetString(); + body.Should().Contain(textFragment); + body.Should().HaveLength(RequestBodyStreamHelper.RequestBodyMaxLength); + } }); } @@ -91,9 +100,13 @@ private async Task Assert_JsonData_RequestBody_IsCaptured(string httpMethod, Sam await SendRequestToSampleAppAndVerifyResponse(new HttpMethod(httpMethod), pathData.Uri, pathData.StatusCode, httpContent: content); await WaitAndCustomVerifyReceivedData(receivedData => { - receivedData.Transactions.Count.Should().Be(1); + receivedData.Transactions.Should().ContainSingle(); var transaction = receivedData.Transactions.Single(); - transaction.Context.Request.Body.Should().Be(jsonBody); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) + { + element.GetString().Should().Be(jsonBody); + } }); } @@ -120,9 +133,13 @@ private async Task Assert_FormData_RequestBody_IsCaptured(string httpMethod, Sam await SendRequestToSampleAppAndVerifyResponse(new HttpMethod(httpMethod), pathData.Uri, pathData.StatusCode, httpContent: content); await WaitAndCustomVerifyReceivedData(receivedData => { - receivedData.Transactions.Count.Should().Be(1); + receivedData.Transactions.Should().ContainSingle(); var transaction = receivedData.Transactions.Single(); - transaction.Context.Request.Body.Should().Be("foo=bar&number=23"); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) + { + element.GetString().Should().Be("foo=bar&number=23"); + } }); } @@ -140,9 +157,13 @@ public async Task FormData_RequestBody_IsCaptured_And_Sanitized() await SendGetRequestToSampleAppAndVerifyResponse(pathData.Uri, pathData.StatusCode, httpContent: content); await WaitAndCustomVerifyReceivedData(receivedData => { - receivedData.Transactions.Count.Should().Be(1); + receivedData.Transactions.Should().ContainSingle(); var transaction = receivedData.Transactions.Single(); - transaction.Context.Request.Body.Should().Be("foo=bar&password=[REDACTED]&number=23"); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) + { + element.GetString().Should().Be("foo=bar&password=[REDACTED]&number=23"); + } }); } @@ -151,26 +172,31 @@ await WaitAndCustomVerifyReceivedData(receivedData => [InlineData("POST")] public async Task MultipartFormData_RequestBody_IsCaptured(string httpMethod) { - using (var tempFile = new TempFile()) + using var tempFile = new TempFile(); + var pathData = SampleAppUrlPaths.HomePage; + + var data = "just some test data in the file"; + var bytes = Encoding.UTF8.GetBytes(data); + + using (var stream = new FileStream(tempFile.Path, FileMode.OpenOrCreate, FileAccess.Write)) + stream.Write(bytes); + + using var content = new MultipartFormDataContent { - var pathData = SampleAppUrlPaths.HomePage; + { new StreamContent(new FileStream(tempFile.Path, FileMode.Open, FileAccess.Read)), "file", "file" } + }; - var data = $"just some test data in the file"; - var bytes = Encoding.UTF8.GetBytes(data); - using (var stream = new FileStream(tempFile.Path, FileMode.OpenOrCreate, FileAccess.Write)) - stream.Write(bytes); - var content = new MultipartFormDataContent - { - { new StreamContent(new FileStream(tempFile.Path, FileMode.Open, FileAccess.Read)), "file", "file" } - }; - await SendRequestToSampleAppAndVerifyResponse(new HttpMethod(httpMethod), pathData.Uri, pathData.StatusCode, httpContent: content); - await WaitAndCustomVerifyReceivedData(receivedData => + await SendRequestToSampleAppAndVerifyResponse(new HttpMethod(httpMethod), pathData.Uri, pathData.StatusCode, httpContent: content); + await WaitAndCustomVerifyReceivedData(receivedData => + { + receivedData.Transactions.Should().ContainSingle(); + var transaction = receivedData.Transactions.Single(); + transaction.Context.Request.Body.Should().BeOfType().Subject.ValueKind.Should().Be(JsonValueKind.String); + if (transaction.Context.Request.Body is JsonElement element) { - receivedData.Transactions.Count.Should().Be(1); - var transaction = receivedData.Transactions.Single(); - transaction.Context.Request.Body.ToString().Should().Contain(data); - }); - } + element.GetString().Should().Contain(data); + } + }); } } } diff --git a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs index 636b01c3f..92a0b45c3 100644 --- a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs +++ b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs @@ -91,9 +91,9 @@ protected TestsBase( private static class DataSentByAgentVerificationConsts { - internal const int LogMessageAfterNInitialAttempts = 30; // i.e., log the first message after 3 seconds (if it's still failing) + internal const int LogMessageAfterNInitialAttempts = 50; // i.e., log the first message after 3 seconds (if it's still failing) internal const int LogMessageEveryNAttempts = 10; // i.e., log message every second (if it's still failing) - internal const int MaxNumberOfAttemptsToVerify = 100; + internal const int MaxNumberOfAttemptsToVerify = 150; internal const int WaitBetweenVerifyAttemptsMs = 100; } From 439438943f1d96c8d98e73592e9ba78a125c82ed Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Wed, 4 Dec 2024 11:34:47 +0000 Subject: [PATCH 11/17] Fix double formatting --- .../Report/Serialization/CustomJsonConverter.cs | 7 +++---- .../Controllers/HomeController.cs | 2 ++ .../Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs b/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs index 793210ec6..d9eacece3 100644 --- a/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs +++ b/src/Elastic.Apm/Report/Serialization/CustomJsonConverter.cs @@ -8,7 +8,6 @@ using System.Text.Json; using System.Text.Json.Serialization; - namespace Elastic.Apm.Report.Serialization; internal class CustomJsonConverter : JsonConverter> @@ -64,13 +63,13 @@ public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOpti public class JsonConverterDouble : JsonConverter { public override double Read(ref Utf8JsonReader reader, - Type typeToConvert, JsonSerializerOptions options) => - reader.GetDouble(); + Type typeToConvert, JsonSerializerOptions options) => reader.GetDouble(); public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) => - writer.WriteRawValue(value.ToString("N1", CultureInfo.InvariantCulture)); + writer.WriteRawValue(value.ToString("0.000", CultureInfo.InvariantCulture)); } + public class JsonConverterDecimal : JsonConverter { public override decimal Read(ref Utf8JsonReader reader, diff --git a/test/iis/AspNetFullFrameworkSampleApp/Controllers/HomeController.cs b/test/iis/AspNetFullFrameworkSampleApp/Controllers/HomeController.cs index 77336e9d0..5156befc2 100644 --- a/test/iis/AspNetFullFrameworkSampleApp/Controllers/HomeController.cs +++ b/test/iis/AspNetFullFrameworkSampleApp/Controllers/HomeController.cs @@ -111,6 +111,8 @@ public Task Contact() return SafeCaptureSpan($"{ContactSpanPrefix}{SpanNameSuffix}", $"{ContactSpanPrefix}{SpanTypeSuffix}", async () => { + await Task.Delay(1000); // Force response to take longer than 1 second to validate formatting of duration. + async Task GetContentFromUrl(Uri url) { Console.WriteLine($"Getting `{url}'..."); diff --git a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs index 92a0b45c3..531f88178 100644 --- a/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs +++ b/test/iis/Elastic.Apm.AspNetFullFramework.Tests/TestsBase.cs @@ -126,14 +126,14 @@ internal static class SampleAppUrlPaths internal static readonly SampleAppUrlPathData PageThatDoesNotExist = new SampleAppUrlPathData("dummy_URL_path_to_page_that_does_not_exist", 404, errorsCount: 1); - internal static readonly List AllPaths = new List - { - new SampleAppUrlPathData("", 200), + internal static readonly List AllPaths = + [ + new("", 200), HomePage, ContactPage, CustomSpanThrowsExceptionPage, PageThatDoesNotExist - }; + ]; /// /// `CallReturnBadRequest' page processing does HTTP Get for `ReturnBadRequest' page (additional transaction) - so 1 span From 51fbbea94c4cfa2ba19f86ff112bc690418c7080 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 12:33:19 +0000 Subject: [PATCH 12/17] Fix FaaS serialization and MockApmServer DTOs --- src/Elastic.Apm/Model/Transaction.cs | 1 + test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs | 1 + test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Elastic.Apm/Model/Transaction.cs b/src/Elastic.Apm/Model/Transaction.cs index 2163a9ad9..928bfcf28 100644 --- a/src/Elastic.Apm/Model/Transaction.cs +++ b/src/Elastic.Apm/Model/Transaction.cs @@ -473,6 +473,7 @@ public string Name /// /// Contains data related to FaaS (Function as a Service) events. /// + [JsonPropertyName("faas")] public Faas FaaS { get; set; } /// diff --git a/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs b/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs index 295d8e046..1a52f83ff 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/FaasDto.cs @@ -9,6 +9,7 @@ namespace Elastic.Apm.Tests.MockApmServer; public class FaasDto { + [JsonPropertyName("cold_start")] public bool ColdStart { get; set; } public string Execution { get; set; } diff --git a/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs b/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs index bdaa9aeb1..1abeab2d2 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/TransactionDto.cs @@ -46,10 +46,10 @@ internal class TransactionDto : ITimedDto public string Type { get; set; } - [JsonPropertyName("dropped_spans_stats")] public List DroppedSpanStats { get; set; } + [JsonPropertyName("faas")] public FaasDto FaaS { get; set; } public override string ToString() => new ToStringBuilder(nameof(TransactionDto)) From 33bf3c572c8950c44e1722154f9ee42177baea50 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 12:59:15 +0000 Subject: [PATCH 13/17] Log deserialization errors in MockApmServer --- .../Controllers/IntakeV2EventsController.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs index 5f93d950b..dce2a7f2d 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/Controllers/IntakeV2EventsController.cs @@ -107,8 +107,18 @@ private async Task ParsePayload() private async Task ParsePayloadLineAndAddToReceivedData(string line) { var foundDto = false; - var payload = JsonSerializer - .Deserialize(line, JsonSerializerOptions) ?? throw new ArgumentException("Deserialization failed"); + + PayloadLineDto payload; + try + { + payload = JsonSerializer.Deserialize(line, JsonSerializerOptions) + ?? throw new ArgumentException("Deserialization failed"); + } + catch (JsonException ex) + { + _logger?.Error()?.LogException(ex, "Failed to deserialize '{Line}'", line); + throw; + } await HandleParsed(nameof(payload.Error), payload.Error, _mockApmServer.ReceivedData.Errors, _mockApmServer.AddError); await HandleParsed(nameof(payload.Metadata), payload.Metadata, _mockApmServer.ReceivedData.Metadata, _mockApmServer.AddMetadata); From 771c3caf323d9dae9dbd51c85e55970ce7bb2317 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 14:32:10 +0000 Subject: [PATCH 14/17] Log failed server response content --- src/Elastic.Apm/Report/IntakeResponse.cs | 1 - src/Elastic.Apm/Report/PayloadSenderV2.cs | 25 ++++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Elastic.Apm/Report/IntakeResponse.cs b/src/Elastic.Apm/Report/IntakeResponse.cs index 25d910c1e..daad7afb6 100644 --- a/src/Elastic.Apm/Report/IntakeResponse.cs +++ b/src/Elastic.Apm/Report/IntakeResponse.cs @@ -19,7 +19,6 @@ internal class IntakeResponse internal class IntakeError { - [JsonPropertyName("message")] public string Message { get; set; } } diff --git a/src/Elastic.Apm/Report/PayloadSenderV2.cs b/src/Elastic.Apm/Report/PayloadSenderV2.cs index cfca94e9e..6cf13681e 100644 --- a/src/Elastic.Apm/Report/PayloadSenderV2.cs +++ b/src/Elastic.Apm/Report/PayloadSenderV2.cs @@ -422,16 +422,7 @@ private void ProcessQueueItems(object[] queueItems) if (response is null || !response.IsSuccessStatusCode) { var message = "Unknown 400 Bad Request"; - if (response?.Content != null) - { -#if NET8_0_OR_GREATER - var intakeResponse = _payloadItemSerializer.Deserialize(response.Content.ReadAsStream()); -#else - var intakeResponse = _payloadItemSerializer.Deserialize(response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()); -#endif - if (intakeResponse.Errors.Count > 0) - message = string.Join(", ", intakeResponse.Errors.Select(e => e.Message).Distinct()); - } + _logger?.Error() ?.Log("Failed sending event." + " Events intake API absolute URL: {EventsIntakeAbsoluteUrl}." @@ -441,6 +432,20 @@ private void ProcessQueueItems(object[] queueItems) , response?.StatusCode, message ); + + if (response?.Content != null) + { + IntakeResponse intakeResponse; +#if NET8_0_OR_GREATER + var responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + _logger?.Warning()?.Log("Received response from server: {ResponseContent}", responseContent); + intakeResponse = _payloadItemSerializer.Deserialize(responseContent); +#else + intakeResponse = _payloadItemSerializer.Deserialize(response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()); +#endif + if (intakeResponse.Errors.Count > 0) + message = string.Join(", ", intakeResponse.Errors.Select(e => e.Message).Distinct()); + } } // ReSharper enable ConditionIsAlwaysTrueOrFalse else From b47e2a146bfe056768e4d91b44c4400122a2185d Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 15:16:05 +0000 Subject: [PATCH 15/17] Profile test tweaks --- src/Elastic.Apm/Report/PayloadSenderV2.cs | 3 +++ test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs | 2 ++ .../RabbitMq/RabbitMqTests.cs | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Elastic.Apm/Report/PayloadSenderV2.cs b/src/Elastic.Apm/Report/PayloadSenderV2.cs index 6cf13681e..f358a33ab 100644 --- a/src/Elastic.Apm/Report/PayloadSenderV2.cs +++ b/src/Elastic.Apm/Report/PayloadSenderV2.cs @@ -393,6 +393,9 @@ private void ProcessQueueItems(object[] queueItems) } } + if (_logger.IsEnabled(LogLevel.Trace)) + + stream.Position = 0; using (var content = new StreamContent(stream)) { diff --git a/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs b/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs index 2dc0d12fa..c0f0ffc61 100644 --- a/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs +++ b/test/Elastic.Apm.Tests.MockApmServer/SpanContextDto.cs @@ -7,6 +7,7 @@ using Elastic.Apm.Helpers; using Elastic.Apm.Model; +using Elastic.Apm.Report.Serialization; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -24,6 +25,7 @@ internal class SpanContextDto : IDto public Http Http { get; set; } [JsonPropertyName("tags")] + [JsonConverter(typeof(LabelsJsonConverter))] public LabelsDictionary Labels { get; set; } public Message Message { get; set; } diff --git a/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs b/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs index 7ee8a3481..2a910e5dd 100644 --- a/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs +++ b/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs @@ -32,7 +32,7 @@ public RabbitMqTests(RabbitMqFixture fixture, ITestOutputHelper output) [InlineData("net8.0")] public async Task CaptureAutoInstrumentedSpans(string targetFramework) { - var apmLogger = new InMemoryBlockingLogger(Logging.LogLevel.Error); + var apmLogger = new InMemoryBlockingLogger(Logging.LogLevel.Warning); var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans)); var port = apmServer.FindAvailablePortToListen(); apmServer.RunInBackground(port); @@ -56,6 +56,9 @@ public async Task CaptureAutoInstrumentedSpans(string targetFramework) exception => _output.WriteLine($"{exception}")); } + foreach (var line in apmLogger.Lines) + _output.WriteLine(line); + var transactions = apmServer.ReceivedData.Transactions; var spans = apmServer.ReceivedData.Spans; From 215e1eaa47871bd5607006a7c15e113f54ad5f24 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 15:39:17 +0000 Subject: [PATCH 16/17] Skip format on Windows due to flakiness --- .github/workflows/test-linux.yml | 1 - .github/workflows/test-windows.yml | 29 +++++++++---------- src/Elastic.Apm/Report/PayloadSenderV2.cs | 3 -- .../ServiceActivationTests.cs | 11 +++---- .../RabbitMq/RabbitMqTests.cs | 2 +- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index e5d20411f..c69ca4766 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -65,7 +65,6 @@ jobs: runs-on: ubuntu-latest needs: [ 'format' ] timeout-minutes: 30 - steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 145e86bbf..bcd6e3c49 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -36,21 +36,19 @@ env: jobs: - format: - runs-on: windows-2022 - steps: - - uses: actions/checkout@v4 - - name: Bootstrap Action Workspace - uses: ./.github/workflows/bootstrap - - name: Format - run: ./build.bat format + # format: + # runs-on: windows-2022 + # steps: + # - uses: actions/checkout@v4 + # - name: Bootstrap Action Workspace + # uses: ./.github/workflows/bootstrap + # - name: Format + # run: ./build.bat format #required step tests: runs-on: windows-2022 - needs: [ 'format' ] timeout-minutes: 30 - steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace @@ -61,9 +59,9 @@ jobs: - name: 'Tests: Unit' run: ./build.bat test --test-suite unit - integrations-tests: + integration-tests: runs-on: windows-2022 - needs: [ 'format', 'tests' ] + needs: [ 'tests' ] steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace @@ -84,7 +82,7 @@ jobs: startup-hook-tests: runs-on: windows-2022 - needs: [ 'format', 'tests' ] + needs: [ 'tests' ] steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace @@ -95,7 +93,7 @@ jobs: profiler-tests: runs-on: windows-2022 - needs: [ 'format', 'tests' ] + needs: [ 'tests' ] steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace @@ -109,8 +107,7 @@ jobs: test-iis: runs-on: windows-latest - needs: [ 'format', 'tests' ] - + needs: [ 'tests' ] steps: - uses: actions/checkout@v4 - name: Bootstrap Action Workspace diff --git a/src/Elastic.Apm/Report/PayloadSenderV2.cs b/src/Elastic.Apm/Report/PayloadSenderV2.cs index f358a33ab..6cf13681e 100644 --- a/src/Elastic.Apm/Report/PayloadSenderV2.cs +++ b/src/Elastic.Apm/Report/PayloadSenderV2.cs @@ -393,9 +393,6 @@ private void ProcessQueueItems(object[] queueItems) } } - if (_logger.IsEnabled(LogLevel.Trace)) - - stream.Position = 0; using (var content = new StreamContent(stream)) { diff --git a/test/Elastic.Apm.Tests/BackendCommTests/ServiceActivationTests.cs b/test/Elastic.Apm.Tests/BackendCommTests/ServiceActivationTests.cs index 9631ae2e8..5046f8ba3 100644 --- a/test/Elastic.Apm.Tests/BackendCommTests/ServiceActivationTests.cs +++ b/test/Elastic.Apm.Tests/BackendCommTests/ServiceActivationTests.cs @@ -31,13 +31,11 @@ public class ServiceActivationTests : LoggingTestBase public ServiceActivationTests(ITestOutputHelper xUnitOutputHelper) : base(xUnitOutputHelper /*, LogLevel.Debug */) => _logger = LoggerBase.Scoped(ThisClassName); - [Fact] public void ShouldNotSendActivationMethodOnceBadVersionIsDiscovered() { var requests = FakeServerInformationCallAndEnqueue("8.7.0"); - requests.Count.Should().Be(3); - + requests.Should().HaveCount(3); requests.Last().Should().NotContain("activation_method"); } @@ -45,8 +43,7 @@ public void ShouldNotSendActivationMethodOnceBadVersionIsDiscovered() public void ShouldSendActivationMethodOtherVersions() { var requests = FakeServerInformationCallAndEnqueue("8.7.1"); - requests.Count.Should().Be(3); - + requests.Should().HaveCount(3); requests.Last().Should().Contain("activation_method"); } @@ -108,6 +105,10 @@ private List FakeServerInformationCallAndEnqueue(string version) agent.PayloadSender.QueueTransaction(new Transaction(agent, "TestName", "TestType")); waitHandle.WaitHandle.WaitOne(TimeSpan.FromSeconds(5)); + + foreach (var request in requests) + LoggerBase?.Info()?.Log("Request: {Request}", request); + return requests; } } diff --git a/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs b/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs index 2a910e5dd..8f5f99e46 100644 --- a/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs +++ b/test/profiler/Elastic.Apm.Profiler.Managed.Tests/RabbitMq/RabbitMqTests.cs @@ -32,7 +32,7 @@ public RabbitMqTests(RabbitMqFixture fixture, ITestOutputHelper output) [InlineData("net8.0")] public async Task CaptureAutoInstrumentedSpans(string targetFramework) { - var apmLogger = new InMemoryBlockingLogger(Logging.LogLevel.Warning); + var apmLogger = new InMemoryBlockingLogger(Logging.LogLevel.Error); var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans)); var port = apmServer.FindAvailablePortToListen(); apmServer.RunInBackground(port); From 6ae5d3508c5c097318abf47cf14ac8b1d35468da Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 5 Dec 2024 18:29:09 +0000 Subject: [PATCH 17/17] Add routing key --- src/Elastic.Apm/Api/Message.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Elastic.Apm/Api/Message.cs b/src/Elastic.Apm/Api/Message.cs index 1d93221f3..dbb864a07 100644 --- a/src/Elastic.Apm/Api/Message.cs +++ b/src/Elastic.Apm/Api/Message.cs @@ -4,6 +4,7 @@ // See the LICENSE file in the project root for more information using System.Collections.Generic; +using System.Text.Json.Serialization; using Elastic.Apm.Api.Constraints; namespace Elastic.Apm.Api @@ -32,6 +33,7 @@ public class Message /// /// optional routing key of the received message as set on the queuing system, such as in RabbitMQ. /// + [JsonPropertyName("routing_key")] public string RoutingKey { get; set; } }