AwsEncryptionSDK/runtimes/net/TestVectorsNative/TestVectorLib/Utils.cs (92 lines of code) (raw):
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace TestVectors
{
public static class Utils
{
public static string GetEnvironmentVariableOrError(string key) {
string nullableResult = Environment.GetEnvironmentVariable(key);
if (nullableResult == null) {
throw new ArgumentException($"Environment Variable {key} must be set");
}
return nullableResult;
}
/// <summary>
/// Check the Environment for a variable.
/// If it exists, pass to function.
/// Otherwise, return default.
/// </summary>
/// <param name="key">Key for Environmental Variable</param>
/// <param name="_default">If key does not exist, use this</param>
/// <param name="stringToValue">If key does exist, pass to this function</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetEnvironmentVariableOrDefault<T>(
string key,
T _default,
Func<string, T> stringToValue)
{
string? nullableResult = Environment.GetEnvironmentVariable(key);
if (nullableResult is null)
{
return _default;
}
return stringToValue(nullableResult);
}
public static T LoadObjectFromPath<T>(string path)
{
if (!File.Exists(path)) {
throw new ArgumentException($"File not found: {path}");
}
string contents = File.ReadAllText(path);
// As a safe-guard against not fully implementing the test vector spec,
// explicitly fail if the file contains any keys we were not expecting
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MissingMemberHandling = MissingMemberHandling.Error;
return JsonConvert.DeserializeObject<T>(contents, settings);
}
/// <summary>
/// Serializes the given object as JSON and writes it to the given path.
/// Throws if the file already exists.
/// <para>
/// Note that NO exception will be thrown if the object has a null value on a required property.
/// </para>
/// </summary>
public static void WriteObjectToPath<T>(T obj, string path)
{
var serializer = new JsonSerializer
{
Formatting = Formatting.Indented,
// WARNING: We set this option in order to omit null optional values.
// But it "overrides" the `JsonRequired` behavior on serialization -
// if the object has a null required value,
// the serializer will just ignore it without throwing an exception.
NullValueHandling = NullValueHandling.Ignore,
};
// Do this first in order to avoid serializing if opening the file fails anyway
using (var fs = new FileStream(path, FileMode.CreateNew))
{
using (var stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, obj);
var bytes = Encoding.UTF8.GetBytes(stringWriter.ToString());
fs.Write(bytes, 0, bytes.Length);
}
}
}
public static string ManifestUriToPath(string uri, string manifestPath) {
// Assumes files referenced in manifests starts with 'file://'
if (!string.Equals(uri.Substring(0, 7), "file://")) {
throw new ArgumentException($"Malformed filepath in manifest (needs to start with 'file://'): {uri}");
}
DirectoryInfo parentDir = Directory.GetParent(manifestPath);
if (parentDir == null)
{
throw new ArgumentException($"Couldn't find parent directory of {manifestPath}");
}
return Path.Combine(parentDir.ToString(), uri.Substring(7));
}
/// <summary>
/// Writes the data of each name-data pair into a new, correspondingly-named file.
/// Throws if any file already exists.
/// </summary>
/// <param name="dir">the directory in which to create new files</param>
/// <param name="namedData">the collection of name-data pairs</param>
public static void WriteNamedDataMap(DirectoryInfo dir, Dictionary<string, MemoryStream> namedData)
{
foreach (var nameDataPair in namedData)
{
WriteBinaryFile(dir, nameDataPair.Key, nameDataPair.Value);
}
}
/// <summary>
/// Writes the given data into a new file.
/// Throws if the file already exists.
/// </summary>
/// <param name="dir">the directory in which to create the new file</param>
/// <param name="name">the name of the file</param>
/// <param name="data">the data to be written</param>
public static void WriteBinaryFile(DirectoryInfo dir, string name, MemoryStream data)
{
var path = dir.FullName + Path.DirectorySeparatorChar + name;
using (var fs = new FileStream(path, FileMode.CreateNew))
{
using (var writer = new BinaryWriter(fs))
{
writer.Write(data.ToArray());
}
}
}
public class InvalidDecryptVectorException : Exception
{
public InvalidDecryptVectorException(string message) : base(message) { }
}
}
}