csharp/AnkiTools/AnkiSharp/Helpers/ShortGuid.cs

ShortGuid.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AnkiSharp.Helpers
{
    /// 
    /// Represents a globally unique identifier (GUID) with a
    /// shorter string value. Sguid
    /// 
    internal struct ShortGuid
    {
        #region Static

        /// 
        /// A read-only instance of the ShortGuid clast whose value
        /// is guaranteed to be all zeroes.
        /// 
        public static readonly ShortGuid Empty = new ShortGuid(Guid.Empty);

        #endregion

        #region Fields

        Guid _guid;
        string _value;

        #endregion

        #region Contructors

        /// 
        /// Creates a ShortGuid from a base64 encoded string
        /// 
        /// The encoded guid as a
        /// base64 string
        public ShortGuid(string value)
        {
            _value = value;
            _guid = Decode(value);
        }

        /// 
        /// Creates a ShortGuid from a Guid
        /// 
        /// The Guid to encode
        public ShortGuid(Guid guid)
        {
            _value = Encode(guid);
            _guid = guid;
        }

        #endregion

        #region Properties

        /// 
        /// Gets/sets the underlying Guid
        /// 
        public Guid Guid
        {
            get { return _guid; }
            set
            {
                if (value != _guid)
                {
                    _guid = value;
                    _value = Encode(value);
                }
            }
        }

        /// 
        /// Gets/sets the underlying base64 encoded string
        /// 
        public string Value
        {
            get { return _value; }
            set
            {
                if (value != _value)
                {
                    _value = value;
                    _guid = Decode(value);
                }
            }
        }

        #endregion

        #region ToString

        /// 
        /// Returns the base64 encoded guid as a string
        /// 
        /// 
        public override string ToString()
        {
            return _value;
        }

        #endregion

        #region Equals

        /// 
        /// Returns a value indicating whether this instance and a
        /// specified Object represent the same type and value.
        /// 
        /// The object to compare
        /// 
        public override bool Equals(object obj)
        {
            if (obj is ShortGuid)
                return _guid.Equals(((ShortGuid)obj)._guid);
            if (obj is Guid)
                return _guid.Equals((Guid)obj);
            if (obj is string)
                return _guid.Equals(((ShortGuid)obj)._guid);
            return false;
        }

        #endregion

        #region GetHashCode

        /// 
        /// Returns the HashCode for underlying Guid.
        /// 
        /// 
        public override int GetHashCode()
        {
            return _guid.GetHashCode();
        }

        #endregion

        #region NewGuid

        /// 
        /// Initialises a new instance of the ShortGuid clast
        /// 
        /// 
        public static ShortGuid NewGuid()
        {
            return new ShortGuid(Guid.NewGuid());
        }

        #endregion

        #region Encode

        /// 
        /// Creates a new instance of a Guid using the string value,
        /// then returns the base64 encoded version of the Guid.
        /// 
        /// An actual Guid string (i.e. not a ShortGuid)
        /// 
        public static string Encode(string value)
        {
            Guid guid = new Guid(value);
            return Encode(guid);
        }

        /// 
        /// Encodes the given Guid as a base64 string that is 22
        /// characters long.
        /// 
        /// The Guid to encode
        /// 
        public static string Encode(Guid guid)
        {
            string encoded = Convert.ToBase64String(guid.ToByteArray());
            encoded = encoded
              .Replace("/", "_")
              .Replace("+", "-");
            return encoded.Substring(0, 22);
        }

        #endregion

        #region Decode

        /// 
        /// Decodes the given base64 string
        /// 
        /// The base64 encoded string of a Guid
        /// A new Guid
        public static Guid Decode(string value)
        {
            value = value
              .Replace("_", "/")
              .Replace("-", "+");
            byte[] buffer = Convert.FromBase64String(value + "==");
            return new Guid(buffer);
        }

        #endregion

        #region Operators

        /// 
        /// Determines if both ShortGuids have the same underlying
        /// Guid value.
        /// 
        /// 
        /// 
        /// 
        public static bool operator ==(ShortGuid x, ShortGuid y)
        {
            if ((object)x == null) return (object)y == null;
            return x._guid == y._guid;
        }

        /// 
        /// Determines if both ShortGuids do not have the
        /// same underlying Guid value.
        /// 
        /// 
        /// 
        /// 
        public static bool operator !=(ShortGuid x, ShortGuid y)
        {
            return !(x == y);
        }

        /// 
        /// Implicitly converts the ShortGuid to it's string equivilent
        /// 
        /// 
        /// 
        public static implicit operator string(ShortGuid shortGuid)
        {
            return shortGuid._value;
        }

        /// 
        /// Implicitly converts the ShortGuid to it's Guid equivilent
        /// 
        /// 
        /// 
        public static implicit operator Guid(ShortGuid shortGuid)
        {
            return shortGuid._guid;
        }

        /// 
        /// Implicitly converts the string to a ShortGuid
        /// 
        /// 
        /// 
        public static implicit operator ShortGuid(string shortGuid)
        {
            return new ShortGuid(shortGuid);
        }

        /// 
        /// Implicitly converts the Guid to a ShortGuid
        /// 
        /// 
        /// 
        public static implicit operator ShortGuid(Guid guid)
        {
            return new ShortGuid(guid);
        }

        #endregion
    }
}