Skip to content

Commit

Permalink
[wip] Initial support for SassTypes.
Browse files Browse the repository at this point in the history
* Added two interface per type, one internal and a public facing
  one to prevent malicious pointers.
* Added dependency walker for SassType for circular references.
  Require extensive testing.
  • Loading branch information
am11 committed Jan 24, 2016
1 parent d5b836c commit 5afa5d6
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 2 deletions.
10 changes: 9 additions & 1 deletion src/LibSass.NET.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="Types\SassUnit.cs" />
<Compile Include="Types\SassListSeparator.cs" />
<Compile Include="Types\SassTypeException.cs" />
<Compile Include="Types\SassNumber.cs" />
<Compile Include="Types\SassMap.cs" />
<Compile Include="Types\SassList.cs" />
<Compile Include="Types\ISassExportableType.cs" />
<Compile Include="Types\SassColor.cs" />
<Compile Include="Types\ISassType.cs" />
<Compile Include="ISassOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SafeSassContextHandle.cs" />
Expand All @@ -53,7 +62,6 @@
<Reference Include="System" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<!-- Build LibSass -->
<Target Name="CopyLibSass" DependsOnTargets="BuildLibSass">
<Exec Command="copy &quot;$(OutDir)x64\libsass.dll&quot; &quot;$(OutDir)libsass.dll&quot;" LogStandardErrorAsError="true" ConsoleToMSBuild="true" />
Expand Down
2 changes: 1 addition & 1 deletion src/SafeSassContextHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected SassResult GetResult()
ErrorJson = PtrToString(sass_context_get_error_json(this)),
ErrorLine = sass_context_get_error_line(this),
ErrorMessage = PtrToString(sass_context_get_error_message(this)),
ErrorSource = PtrToString(sass_context_get_error_src(this)),
//ErrorSource = PtrToString(sass_context_get_error_src(this)),
ErrorStatus = sass_context_get_error_status(this),
ErrorText = PtrToString(sass_context_get_error_text(this)),
SourceMap = PtrToString(sass_context_get_source_map_string(this)),
Expand Down
9 changes: 9 additions & 0 deletions src/SassExterns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ public partial class SassCompiler
{
public const string _libName = "libsass";

[DllImport(_libName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sass_make_list(int @length, Types.SassListSeparator @sep);

[DllImport(_libName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void sass_list_set_value(IntPtr @value_list, int @size, IntPtr @value);

[DllImport(_libName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sass_make_number(double @value, string @unit);

[DllImport(_libName, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr sass_delete_data_context(IntPtr @context);

Expand Down
12 changes: 12 additions & 0 deletions src/Types/ISassExportableType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Sass.Types
{
internal interface ISassExportableType
{
/// <summary>
/// Intantiate the type on LibSass heap.
/// </summary>
IntPtr GetInternalTypePtr();
}
}
5 changes: 5 additions & 0 deletions src/Types/ISassType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Sass.Types
{
public interface ISassType
{ }
}
20 changes: 20 additions & 0 deletions src/Types/SassColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Sass.Types
{
public class SassColor: ISassType, ISassExportableType
{
public double Value { get; set; }
public SassUnit Unit { get; set; }

public override string ToString()
{
return $"{Value}{Unit}";
}

IntPtr ISassExportableType.GetInternalTypePtr()
{
return SassCompiler.sass_make_number(Value, Unit.ToString());
}
}
}
72 changes: 72 additions & 0 deletions src/Types/SassList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sass.Types
{
public class SassList : ISassType, ISassExportableType
{
public List<ISassType> Values { get; set; } = new List<ISassType>();
public SassListSeparator Separator { get; set; } = SassListSeparator.Space;

private bool _ensured;

/// <summary>
/// Recursively ensures:
/// * Arbitrary ISassType implementation.
/// * Circular reference on each "listy" item stored in the values.
/// </summary>
/// <param name="lists">List containing instances of SassList</param>
internal static void WalkAndEnsureDependencies(SassList list, List<SassList> lists)
{
// Prevent from re-entrance.
if (list._ensured)
return;

// FIXME: Should we instead loop through the array and
// report the exact index which violates this rule?
if (!list.Values.All(v => v is ISassExportableType))
{
throw new SassTypeException(
@"The value must not contain an object of type that is an arbitrary implementation
of ISassType. Please use the predefined Sass types or extend the predefined type's
functionality using inheritance or extension methods.");

This comment has been minimized.

Copy link
@darrenkopp

darrenkopp Jan 25, 2016

using @ for strings is gonna make it so you have new lines in your exception message. not sure if this was intended or if you are just doing this for code formatting. you likely don't want the newlines in the exception message

This comment has been minimized.

Copy link
@am11

am11 Jan 25, 2016

Author Owner

Thanks. I think line breaks will appear end up in exception message, will check and fix accordingly. :)

}

// Detect the circular-referencing values.
lists.Add(list);

var filteredValues = list.Values
.Where(v => v is SassList)
.Select(v => v as SassList).ToList();

if (filteredValues.Any(v => lists.Contains(v)))

This comment has been minimized.

Copy link
@darrenkopp

darrenkopp Jan 25, 2016

lines 39 - 43 can be comined into

var filteredValues = list.Values.OfType<SassList>().ToList()
if (filteredValues .Any(v => lists.Contains(v))

OfType does exactly what your .Where().Select() combo is doing

This comment has been minimized.

Copy link
@am11

am11 Jan 25, 2016

Author Owner

Great! Never used OfType before. Will fix. 👍

throw new SassTypeException(
@"Circular reference detected. Values cannot contain
self-referencing instance.");

filteredValues.ForEach(v => WalkAndEnsureDependencies(v, lists));
list._ensured = true;
}

public override string ToString()
{
return string.Join(Separator.ToString(), Values.Select(v => v.ToString()));
}

IntPtr ISassExportableType.GetInternalTypePtr()
{
WalkAndEnsureDependencies(this, new List<SassList>());

var list = SassCompiler.sass_make_list(Values.Count, Separator);

for (int index = 0; index < Values.Count; ++index)
{
SassCompiler.sass_list_set_value(list, index,
(Values[index] as ISassExportableType).GetInternalTypePtr());
}

return list;
}
}
}
8 changes: 8 additions & 0 deletions src/Types/SassListSeparator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Sass.Types
{
public enum SassListSeparator
{
Comma = ',',
Space = ' '
}
}
20 changes: 20 additions & 0 deletions src/Types/SassMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Sass.Types
{
public class SassMap : ISassType, ISassExportableType
{
public double Value { get; set; }
public SassUnit Unit { get; set; }

public override string ToString()
{
return $"{Value}{Unit}";
}

IntPtr ISassExportableType.GetInternalTypePtr()
{
return SassCompiler.sass_make_number(Value, Unit.ToString());
}
}
}
20 changes: 20 additions & 0 deletions src/Types/SassNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Sass.Types
{
public class SassNumber : ISassType, ISassExportableType
{
public double Value { get; set; }
public SassUnit Unit { get; set; }

public override string ToString()
{
return $"{Value}{Unit}";
}

IntPtr ISassExportableType.GetInternalTypePtr()
{
return SassCompiler.sass_make_number(Value, Unit.ToString());
}
}
}
9 changes: 9 additions & 0 deletions src/Types/SassTypeException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Sass.Types
{
public class SassTypeException : Exception
{
public SassTypeException(string message) : base(message) { }
}
}
7 changes: 7 additions & 0 deletions src/Types/SassUnit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Sass.Types
{
public enum SassUnit
{
IN, CM, PC, MM, PT, PX
}
}

0 comments on commit 5afa5d6

Please sign in to comment.