Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
25e4499d9This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Hast.Common.Helpers;
using Hast.Layer;
using Hast.Remote.Bridge.Models;
using Hast.Transformer.Abstractions;
namespace Hast.Remote.Client
{
public class RemoteTransformer : ITransformer
{
public async Task<IHardwareDescription> Transform(IEnumerable<string> assemblyPaths, IHardwareGenerationConfiguration configuration)
{
var apiClient = ApiClientFactory.CreateApiClient(configuration.RemoteClientConfiguration());
var assemblyContainers = assemblyPaths
.Select(path => new AssemblyContainer
{
Name = Path.GetFileNameWithoutExtension(path),
FileContent = File.ReadAllBytes(path)
});
var apiConfiguration = new Bridge.Models.HardwareGenerationConfiguration
{
CustomConfiguration = configuration.CustomConfiguration,
DeviceName = configuration.DeviceName,
HardwareEntryPointMemberFullNames = configuration.HardwareEntryPointMemberFullNames,
HardwareEntryPointMemberNamePrefixes = configuration.HardwareEntryPointMemberNamePrefixes
};
var transformationTicket = await apiClient
.RequestTransformation(new TransformationRequest
{
Assemblies = assemblyContainers,
Configuration = apiConfiguration
});
TransformationResult transformationResult = null;
const int maxResultAttemptCount = 100;
var waitAttemptIndex = 0;
var waitMilliseconds = 333;
while (transformationResult == null && waitAttemptIndex < maxResultAttemptCount)
{
await Task.Delay(waitMilliseconds);
var transformationResultResponse = await apiClient.GetTransformationResult(transformationTicket.Token);
if (transformationResultResponse.ResponseMessage.IsSuccessStatusCode)
{
transformationResult = transformationResultResponse.GetContent();
}
else if (transformationResultResponse.ResponseMessage.StatusCode != System.Net.HttpStatusCode.NotFound)
{
transformationResultResponse.ResponseMessage.EnsureSuccessStatusCode();
}
if (++waitAttemptIndex % 10 == 0) waitMilliseconds *= 2;
}
var exceptionMessageBase =
"Transforming the following assemblies failed: " + string.Join(", ", assemblyPaths) + ". ";
if (transformationResult == null)
{
throw new Exception(
exceptionMessageBase + "The remote Hastlayer service didn't produce a result in a timely manner. " +
"This could indicate a problem with the service or that the assemblies contained exceptionally complex code.");
}
if (transformationResult.Errors?.Any() == true)
{
throw new Exception(
exceptionMessageBase + "The following error(s) happened: " + Environment.NewLine +
string.Join(Environment.NewLine, transformationResult.Errors));
}
var hardwareDescription = transformationResult.HardwareDescription;
return new RemoteHardwareDescription
{
HardwareEntryPointNamesToMemberIdMappings = hardwareDescription.HardwareEntryPointNamesToMemberIdMappings,
Language = hardwareDescription.Language,
Source = hardwareDescription.Source,
Warnings = hardwareDescription.Warnings.Select(warning =>
new Common.Models.TransformationWarning { Code = warning.Code, Message = warning.Message })
};
}
private class RemoteHardwareDescription : IHardwareDescription
{
public IReadOnlyDictionary<string, int> HardwareEntryPointNamesToMemberIdMappings { get; set; }
public string Language { get; set; }
public string Source { get; set; }
public IEnumerable<ITransformationWarning> Warnings { get; set; }
public Task WriteSource(Stream stream)
{
using (var streamWriter = new StreamWriter(stream))
{
// WriteAsync would throw a "The stream is currently in use by a previous operation on the stream." for
// FileStreams, even though supposedly there's no operation on the stream.
streamWriter.Write(Source);
}
return Task.CompletedTask;
}
}
}
}