Attached is an implementation of the methods and classes from external library 
digest.so that are used by some simple Rails use cases.

-----------------------------------------------------------------------------------------

I note, that the IronRuby pattern for supporting custom object cloning it to 
implement the IDuplicable interface. Is there some reason for this approach 
rather than using Ruby's standard mechanism of implementing an initialize_copy 
method? With the latter approach, Ruby programmers can implement their own copy 
semantics, eg:

class Foo
    def initialize_copy(c)
      puts 'copying'
    end
end
f = Foo.new
g = f.clone


Cheers, Wayne.
using Ruby;
using Ruby.Runtime;
using Ruby.Builtins;
using Microsoft.Scripting.Ast;
using Microsoft.Scripting.Actions;
using Microsoft.Scripting.Runtime;
using System.Security.Cryptography;



[RubyModule("Digest")]
public static class Digest
{
    [RubyClass("MD5")]
    public class MD5: Base
    {
        public MD5()
        {
            algorithm = System.Security.Cryptography.MD5.Create();
        }
    }

    [RubyClass("Base")]
    public class Base: DigestClass, IDuplicable
    {
        public HashAlgorithm algorithm;
        public MutableString buffer = new MutableString();

        [RubyMethod("<<")]
        [RubyMethod("update")]
        public static object digest_base_update(CodeContext context, Base self, 
MutableString str)
        {
            self.buffer.Append(str);           
            return self;
        }

        [RubyMethod("finish", RubyMethodAttributes.PrivateInstance)]
        public static MutableString finish(CodeContext context, Base self)
        {
            byte[] input = self.buffer.ToByteArray();
            byte[] hash = self.algorithm.ComputeHash(input);
            return new MutableString(hash, 0, hash.Length);
        }

        [RubyMethod("reset")]
        public static object reset(CodeContext context, Base self)
        {
            self.buffer = new MutableString();
            self.algorithm.Initialize();
            return self;
        }

        //TODO: should this be initialize_copy method?
        public void InitializeFrom(object copy_from)
        {
            buffer = new MutableString(((Base)copy_from).buffer);
        }
    }

    [RubyClass("Class"), Includes(typeof(Instance))]
    public class DigestClass
    {
        [RubyMethod("digest", RubyMethodAttributes.PublicSingleton)]
        public static MutableString digest(CodeContext context, RubyClass 
klass, MutableString str)
        {
            object obj = RubySites.Allocate(context, klass);
            return Call_digest(context, obj, str);
        }

        [RubyMethod("hexdigest", RubyMethodAttributes.PublicSingleton)]
        public static MutableString hexdigest(CodeContext context, RubyClass 
klass, MutableString str)
        {
            return hexencode(Call_digest(context, klass, str));
        }

        #region Helpers
        internal static MutableString Bytes2Hex(byte[] bytes)
        {
            return new 
MutableString(System.BitConverter.ToString(bytes).Replace("-", "").ToLower());
        }

        internal static MutableString hexencode(MutableString str)
        {
            return Bytes2Hex(str.ToByteArray());
        }
        #endregion

        #region DynamicSites
        private static DynamicSite<object, MutableString, MutableString> 
DigestSharedSite = DynamicSite<object, MutableString, 
MutableString>.Create(RubySites.InstanceCallAction("digest", 
ArgumentKind.Simple));

        private static MutableString Call_digest(CodeContext/*!*/ context, 
object self, MutableString str)
        {
            return DigestSharedSite.Invoke(context, self, str);
        }
        #endregion
    }

    [RubyModule("Instance")]
    public class Instance
    {
        [RubyMethod("digest")]
        public static MutableString digest(CodeContext context, object self, 
MutableString str)
        {
            Call_reset(context, self);
            Call_update(context, self, str);
            MutableString value = Call_finish(context, self);
            Call_reset(context, self);

            return value;
        }

        [RubyMethod("hexdigest")]
        public static MutableString hexdigest(CodeContext context, Base self)
        {
            object clone = Kernel.Clone(context, self);
            MutableString str = Call_finish(context, clone);
            Call_reset(context, clone);
            return DigestClass.hexencode(str);
        }

        #region DynamicSites
        private static DynamicSite<object, object> ResetSharedSite = 
DynamicSite<object, object>.Create(RubySites.InstanceCallAction("reset"));

        private static object Call_reset(CodeContext/*!*/ context, object self)
        {
            return ResetSharedSite.Invoke(context, self);
        }

        private static DynamicSite<object, MutableString, object> 
UpdateSharedSite = DynamicSite<object, MutableString, 
object>.Create(RubySites.InstanceCallAction("update", ArgumentKind.Simple));

        private static object Call_update(CodeContext/*!*/ context, object 
self, MutableString str)
        {
            return UpdateSharedSite.Invoke(context, self, str);
        }

        private static DynamicSite<object, MutableString> FinishSharedSite = 
DynamicSite<object, 
MutableString>.Create(RubySites.InstanceCallAction("finish"));

        private static MutableString Call_finish(CodeContext/*!*/ context, 
object self)
        {
            return FinishSharedSite.Invoke(context, self);
        }
        #endregion
    }
}

Attachment: digest_test.rb
Description: digest_test.rb

_______________________________________________
Ironruby-core mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to