Ruby/Marshal
تحوّل المكتبة Marshal
مجموعات من كائنات روبي إلى مجرى من البايتات (byte stream)، مما يسمح بتخزينها خارج البرنامج النصي النشط حاليًا. يمكن بعد ذلك قراءة تلك البيانات وإعادة إنشاء الكائنات الأصلية أنشئت منها.
تحتوي البيانات المرصوفة (Marshaled data) على أرقام الإصدار الرئيسية والثانوية مخزنةً مع معلومات الكائن. في الاستخدام العادي، تُحمّل فقط البيانات التي لها نفس رقم الإصدار الرئيسي، ورقم الإصدار الثانوي المساوي أو الأقل منه. وفي حال ضبط قيمة الراية "verbose
" (عادةً باستخادم -d
أو -v
أو -w
أو -verbose
) يجب أن تتطابق الأرقام الرئيسية والثانوية تمامًا. إصدارات Marshal
مستقلة عن إصدار روبي المستخدم. يمكنك استخلاص رقم الإصدار عن طريق قراءة أول بايتين من البيانات المرصوفة.
str = Marshal.dump("thing")
RUBY_VERSION #=> "1.9.0"
str[0].ord #=> 4
str[1].ord #=> 8
لا يمكن تفريغ بعض الكائنات: في حال محاولة تفريغ كائنات تتضمن ارتباطات (bindings) أو إجراءات (procedure) أو توابع، أو كائنات IO
، أو كائنات أحادية (singleton)، فسيطلق الخطأ TypeError
.
إن كنت تريد تسلسلًا (serialization) مخصصًا (مثل إذا كنت تريد إجراء التسلسل وفق تنسيق معين)، أو إذا كان الصنف يحوي كائنات غير قابلة للتسلسل، فيمكنك إعداد قواعد التسلسل الخاصة بك.
هناك طريقتان للقيام بذلك، يمكن للكائنات أن تعرّف إما marshal_dump
و marshal_load
أو _dump
و _load
. يملك marshal_dump
أولويةً على _dump
في حال تعريف كليهما. قد يُنتج marshal_dump
سلاسل نصية أصغر.
تحسُّبات أمنية
يمكن للتابع load
فك تسلسل (deserialize) أي صنف مُحمّل في عمليات روبي تقريبًا. في العديد من الحالات، يمكن أن يؤدي ذلك إلى تنفيذ التعليمات البرمجية عن بُعد إن حُملت البيانات المرصوفة (Marshal data) من مصدر غير موثوق به.
نتيجة لذلك، التابع load::
ليس مناسبًا ليكون تنسيقَ تسلسلٍ عامٍّ، ويجب ألا يتم تبديد (unmarshal) البيانات المُدخلة من قبل المستخدم أو غيرها من البيانات غير الموثوقة.
إذا كنت تريد فك تسلسل (deserialize) البيانات غير الموثوقة، فاستخدم JSON أو تنسيق تسلسل آخر لا يمكنه أن يحمّل إلا الأنواع "البدائية" البسيطة، مثل السلاسل النصية والمصفوفات وجداول Hash وما إلى ذلك. لا تسمح أبدًا لمدخلات المستخدم أن تحدد أنواعًا عشوائيةً لفك التسلسل.
التابع marshal_dump
والتابع marshal_load
عند تفريغ (dumping) كائن، سيتم استدعاء التابع marshal_dump
. يجب أن يعيد التابع marshal_dump
نتيجةً تحتوي على المعلومات الضرورية للتابع marshal_load
لإعادة إنشاء الكائن. النتيجة يمكن أن تكون أي كائن.
عند تحميل كائن تم تفريغه باستخدام marshal_dump
، يتم أولاً تحديد الكائن، ثم يُستدعَى التابع marshal_load
وتُمرّر إليه النتيجة المُعادة من التابع marshal_dump
. يجب أن يعيد التابع marshal_load
إنشاء الكائن انطلاقًا من المعلومات المُتضمنة في النتيجة.
اطلع على المثال التالي:
class MyObj
def initialize name, version, data
@name = name
@version = version
@data = data
end
def marshal_dump
[@name, @version]
end
def marshal_load array
@name, @version = array
end
end
التابع _dump
والتابع _load
استخدم التابعين _dump
و _load
عندما تريد تحديد الكائن الذي تود استعادته بنفسك.
عند تفريغ كائن، يُستدعى التابع _dump
مع تمرير عدد صحيح إليه يشير إلى العمق الأقصى للكائنات التى ستُفرّغ (القيمة -1
تعني يجب عليك تعطيل التحقق من العمق). يجب أن يعيد التابع _dump
سلسلةً نصيةً تحتوي على المعلومات الضرورية لإعادة إنشاء الكائن.
يأخذ الصنف method_load
سلسلةً نصيةً ويستخدمها لإعادة كائن من نفس الصنف.
إليك المثال التالي:
class MyObj
def initialize name, version, data
@name = name
@version = version
@data = data
end
def _dump level
[@name, @version].join ':'
end
def self._load args
new(*args.split(':'))
end
end
لما كان التابع dump
يعيد سلسلة نصية، يمكنك جعل التابع have_dump
يعيد سلسلة مرصوفة (Marshal string)،
الثوابت
MAJOR_VERSION
يمثِّل الإصدار الرئيسي.
MINOR_VERSION
يمثِّل الإصدار الثانوي.
توابع الصنف العامة (Public Class Methods)
dump
يُسلسل (Serializes) الكائن المعطى وجميع الكائنات المنحدرة منه (descendant objects). في حال تمرير كائن من النوع IO
، فستُكتب البيانات المُسَلسلة فيه، وإلا فستُعاد البياناتكسلسلة نصية.
load
يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).
restore
يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).